XML-Header
|
Standard XML-Header
|
cookml
|
Root of the actual
data
|
cookml : version
|
Revision number of the
CML specification use to create the instance file
|
cookml : name
|
Name of the recipe
collection contained in this file
|
cookml : prog
|
Name of the program
which generated this instance
|
cookml : progver
|
Version number of
“prog”
|
cookml : recipe
|
Root of the individual
recipe
|
cookml : recipe : lang
|
Language used in the
recipe
|
cookml : recipe : head
|
Informational data to
a recipe
|
cookml : recipe : head : title
|
Title of the recipe
|
cookml : recipe : head : rid
|
Unique recipe
identifier
|
cookml : recipe : head : servingqty
|
Serving quantity
|
cookml : recipe : head : servingtype
|
Unit of serving
quantity (person, piece, etc.)
|
cookml : recipe : head : createdate
|
Creating date
|
cookml : recipe : head : createuser
|
Creator/Recorder of
recipe
|
cookml : recipe : head : createemail
|
EMail of creator
|
cookml : recipe : head : changedate
|
Date of the most
recent change
|
cookml : recipe : head : changeuser
|
Person, who made the
most recent change
|
cookml : recipe : head : changeemail
|
EMail of “changeuser”
|
cookml : recipe : head : timeallqty
|
Total preparation time
for the recipe
|
cookml : recipe : head : timeprepqty
|
Preparation time
|
cookml : recipe : head : timecookqty
|
Cooking time
|
cookml : recipe : head : costs
|
Cost of the recipe
|
cookml : recipe : head : country
|
Producing country
|
cookml : recipe : head
: proteins |
Quantity of proteins |
cookml : recipe : head
: carbohydrates |
Quantity of carbohydrates |
cookml : recipe : head
: fat |
Quantity of fat |
cookml : recipe : head : wwpoints
|
Weight-Watcher points or something like that
|
cookml : recipe : head : cat
|
Categories (recipe
grouping)
|
cookml : recipe : head : hint
|
Key words for the
recipe
|
cookml : recipe : head : sourceline
|
Free format
information to the recipe source
|
cookml : recipe : head : card
|
Detailed description
of the recipe (e.g. for a restaurant menu)
|
cookml : recipe : head
: allergies |
Allergic substances |
cookml : recipe : head :
allergies : allergy |
Data for an allergic substance |
cookml : recipe : head :
allergies : allergy : name |
Name of the allergic substance |
cookml : recipe : head :
allergies : allergy : contains |
Is allergic substance in the recipe |
cookml : recipe : head : content
|
Information on
substances contained in recipe ingredients
|
cookml : recipe : head : content : type
|
Type of substance
|
cookml : recipe : head : content : value
|
Value/quantity of
substance
|
cookml : recipe : head : picture
|
Image of the recipe
|
cookml : recipe : head : picture : file
|
Path to the image,
either local or on the web
|
cookml : recipe : head : picbin
|
Image of the recipe,
embedded in the XML file
|
cookml : recipe : head : picbin :
format
|
Format of the embedded
image
|
cookml : recipe : custom
|
Field for additional
data
|
cookml : recipe : custom : name
|
Name of the “custom”
field
|
cookml : recipe : custom : datatype
|
Data type of the
“custom” field
|
cookml : recipe : custom : value
|
Value of the “custom”
field
|
cookml : recipe : part
|
Grouping of an
ingredient unit
|
cookml : recipe : part:: title
|
Title of the
ingredient unit
|
cookml : recipe : part:: ingredient
|
Ingredient (root of
each ingredient)
|
cookml : recipe : part : ingredient : qty
|
Required quanity of
ingredient
|
cookml : recipe : part : ingredient : unit
|
Unit of the ingredient
|
cookml : recipe : part : ingredient : item
|
Name of the ingredient
|
cookml : recipe : part : ingredient : inote
|
Additional
information, explanations to the ingredient
|
cookml : recipe : part : ingredient : bls
|
The ingredients
BLS-Code (BLS - Bundeslebensmittelschlüssel
|
cookml : recipe : part : ingredient : gram
|
Approximite value in
grams for units which are not directly convertible
|
cookml : recipe : part : ingredient : shop
|
Flag, ob Zutat auf
Einkaufslisten soll
|
cookml : recipe : part : ingredient : calc
|
Flag, to define if
ingredient should be considered in the nutrional calculation
|
cookml : recipe : part : ingredient
: ridlink
|
RID to a recipe which
is used as an ingredient
|
cookml : recipe : part : ingredient
: preparation
|
Preparation
instructions for this particular ingredient
|
cookml : recipe : preparation
|
Preparation/Recipe
instructions
|
cookml : recipe : preparation : text
|
Preparation
instructions as a block of text
|
cookml : recipe : preparation : step
|
Prepartion
instructions as individual steps
|
cookml : recipe : remark
|
Remarks of a user/cook
|
cookml : recipe : remark : user
|
The name of the person
making the remark
|
cookml : recipe : remark : line
|
The remark
|
cookml : menu
|
The root of a menu
|
cookml : menu : title
|
Name of the menu
|
cookml : menu : mcustom
|
Field for additional
data
|
cookml : menu : mcustom : name
|
Name of the “mcustom”
field
|
cookml : menu : mcustom : datatype
|
Data type of the
“mcustom” field
|
cookml : menu : mcustom : value
|
Value of the “mcustom”
field
|
cookml : menu : mrecipe
|
Recipe of a menu
|
cookml : menu : mrecipe : title
|
Title of the recipe
menu item
|
cookml : menu : mrecipe : rid
|
“rid” -
recipe identifier of the recipe menu item
|
cookml : menu : mrecipe : amount
|
Quantity for the
recipe menu item (in the unit of the recipe)
|
cookml : menu : mrecipe : persons
|
Quantity of the menu
item (always in the unit “person”)
|
cookml : menu : mrecipe : desc
|
Additional information
to the recipe menu item
|
|
|
Producing country
Descripes the country or area, from which the recipe comes from.
Data type: |
string, XML-attribut of
head |
Supported: |
optional |
Compatibility: |
KalorioNext |
cookml
: recipe : head :
proteins
Quantity of proteins
Describes the quantity of proteins from the calories.
All data should be given for one portion, so the portion-calculations must not recalc this string-data.
Datentyp: |
string,
XML-Attribut, Singulär |
Unterstützung: |
Optional |
Kompatibilität: |
Kalorio |
cookml
: recipe : head :
carbohydrates
Quantity of carbohydrates
Describes the quantity of carbohydrates from the calories.
All data should be given for one portion, so the portion-calculations must not recalc this string-data.
Datentyp: |
string,
XML-Attribut, Singulär |
Unterstützung: |
Optional |
Kompatibilität: |
Kalorio |
cookml
: recipe : head :
fat
Quantity of fat
Describes the quantity of fat from the calories.
All data should be given for one portion, so the portion-calculations must not recalc this string-data.
Datentyp: |
string,
XML-Attribut, Singulär |
Unterstützung: |
Optional |
Kompatibilität: |
Kalorio |
cookml
: recipe : head
: wwpoints
Weight-Watcher points
The
Weight-Watcher users have often contacted me, that they require a
field to record the points. The points will be assigned to a recipe
as a whole and for all the portions defined for the recipe.
Data type:
|
float, XML-Attribut,
unique
|
Supported:
|
optional
|
Compatibility:
|
Kalorio
|
cookml
: recipe : head
: cat
Categories (recipe groupings)
In each
“cat” element one defines a recipe category. The recipe
categories are not defined, are therefore left to the user and can be
different from user to user.
It is planned to standardise a certain number
of categories.
Data type:
|
string, XML-Element,
sequence
|
Supported:
|
mandatory
|
Compatibility:
|
all
|
cookml
: recipe : head
: sourceline
Source
If the source of the recipe is
known, one should (to be fair to the original author) use this
element to provide this information.
Data type:
|
string, XML-Element,
sequence
|
Supported:
|
mandatory
|
Compatibility:
|
all
|
cookml
: recipe : head
: hint
Key words for the recipe
For each
recipe any number of key words can be defined. Often this key words
are used for searches. Contrary to “ing:cat” there are
not plans to standardize these, therefore anyone can define words
which work for them.
Data type:
|
string, XML-Element,
sequence
|
Supported:
|
optional
|
Compatibility:
|
Ambrosia, Kalorio
|
cookml
: recipe : head
: card
Detailed description of the recipe (e.g. for
restaurant menu)
If a recipe collection is used to create a
restaurant menu these elements can be used to provide further
explanation of the recipe or to translate the description into other
languages.
Data type:
|
string, XML-Element,
sequence
|
Supported:
|
optional
|
Compatibility:
|
Ambrosia
|
cookml
: recipe : head
: content
Content of a recipe (by substance)
Here
you can enter the total of all ingredients for a certain substance as
per the Bundelebensmittelschlüssel. Most programs will define
here the calories, but it could also be used for things such as
vitamines or bread units etc.
A record is made up of 2 parts: The substance
(key = short name as per Bundelebensmittelschlüssel) and the
quantity (same unit as defined in the Bundelebensmittelschlüssel).
Exceptions:
1. only quantitativ
BLS-substances (the BLS database defines this information). Strings
like e.g. “BLS-Code” are not useful here, it is also
defined in this list.
Example:
<content type="GCAL"
value="627"/> // Calories in kCal
<content
type="GKB" value="42"/> // bread units
Data type:
|
complex type,
XML-Element, sequence
|
Supported:
|
optional
|
Compatibility:
|
Kalorio
|
cookml
: recipe : head
: content : type
Code of the substance
Description see
recipe:content
Data type:
|
string, XML-Attribut
from content
|
Supported:
|
optional
|
Compatibility:
|
Ambrosia, Kalorio
|
cookml
: recipe : head : allergies
Allergic substances
All allergic substances are collected in this tag
Datentyp: |
string, XML-Element, Single |
Unterstützung: |
Optional |
Kompatibilität: |
Kalorio |
cookml
: recipe : head : allergies : allergy
Data of an allergic substance
Data for one allergic substance.
Datentyp: |
string, XML-Element, Sequenz |
Unterstützung: |
Optional |
Kompatibilität: |
Kalorio |
cookml
: recipe : head : allergies : allergy : name
Name of the allergic substance
Datentyp: |
string, XML-Element |
Unterstützung: |
Optional |
Kompatibilität: |
Kalorio |
cookml
: recipe : head : allergies : allergy : contains
Is the substance containing
'F'=free of this substance, 'C'-contains this substance
Datentyp: |
string, XML-Element |
Unterstützung: |
Optional |
Kompatibilität: |
Kalorio |
cookml
: recipe : head
: content : value
Quantity of the substance
Description
see recipe:content
Data type:
|
string, XML-Attribut
von content
|
Supported:
|
optional
|
Compatibility:
|
Ambrosia, Kalorio
|
cookml
: recipe : head
: picture
Recipe image (file name)
Define here
the image of the recipe in the form of a file name, without the path.
The file is only locally on the user hard disk, this is only useful
if the file hirarchy is always the same or if the images are stored
in a defined folder.
Data type:
|
complex type,
XML-Element, sequence
|
Supported:
|
optional
|
Compatibility:
|
Ambrosia, Kalorio
|
cookml
: recipe : head
: picture
:
file
Path to the image file, local or on the
network
Define here the image file name or a complet URL (e.g.
http://www.somewebsite.com/anyfilename.JPG), the format is not
defined but JPG is prefered due to it's common use and support.
Data type:
|
string, XML-Attribut,
unique
|
Supported:
|
optional
|
Compatibility:
|
Ambrosia, Kalorio
|
cookml
: recipe : head
: picbin
Recipe image embedded in the XML instance as
binary data
The image is embedded in the XML instance file,
the image has to be mime64 encoded.
Data type:
|
mime64, XML-Element,
sequence
|
Supported:
|
optional
|
Compatibility:
|
Kalorio
|
cookml
: recipe : head
: picbin
:
format
Format of the image file
To ensure a
good/correct handling of the embedded image, you have to provide the
format of the image.
You have to use one of the following extension
in upper case only.
Currently supported: BMP, JPG, PNG, TIF
Data type:
|
string, XML-Attribut,
unique
|
Supported:
|
mandatory
|
Compatibility:
|
Kalorio
|
cookml
: recipe : head
: custom
Custom element definiton
This tag
allows to include any type of information not currently supported by
CookML. Keep in mind that this information will not be processed by
other programs and one should not use this extensively, instead you
should contact the author and request an enhancement/inclusion into
the CookML standard for the type of information you want to pass on
using the tag.
"custom" is made up of the attributes
"name", "datatype" and "value", which
should all be self explanatory.
Data type:
|
string, XML-Element,
sequence
|
Supported:
|
optional
|
Compatibility:
|
Kalorio
|
cookml
: recipe : head
: custom : name
Name of a custom element
Description
see "cookml:recipe:custom"
Data type:
|
string, XML-Attribut
|
Supported:
|
mandatory
|
Compatibility:
|
Kalorio
|
cookml
: recipe : head
: custom : datatype
Data type of a costum field
Description
see "cookml:recipe:custom"
Data type:
|
string, XML-Attribut
|
Supported:
|
mandatory
|
Compatibility:
|
|
cookml
: recipe : head
: custom : value
Wert eines freien Feldes
Beschreibung
siehe "cookml:recipe:custom"
Data type:
|
string, XML-Attribut
|
Supported:
|
mandatory
|
Compatibility:
|
Kalorio
|
cookml
: recipe :
part
Definition of an ingredient
group
Ingredients are often sorted to form groups (e.g.
Pastry, Filling). You can define such a group here. You can assign a
heading to this group using the attribute title.
Data type:
|
complex type,
XML-Element, sequence
|
Supported:
|
mandatory
|
Compatibility:
|
all
|
cookml
: recipe :
part
: title
Definition of an ingredient
group
Ingredients are often sorted to form groups (e.g.
Pastry, Filling). You can define such a group here. You can assign a
heading to this group using the attribute title.
Data type:
|
complex type,
XML-Attribut
|
Supported:
|
mandatory
|
Compatibility:
|
all
|
cookml
: recipe :
part
: ingredient
Ingredient (root of an ingredient)
The
start of a new ingredient.
Data type:
|
complex type,
XML-Element, sequence
|
Supported:
|
mandatory
|
Compatibility:
|
all
|
cookml
: recipe :
part
: ingredient : qty
Quantity of the ingredient
Enter here
a number for the quantity of the ingredient. The number refers to
“ing:unit”. Only decimal numbers are allowed. Fractions
have to be converted to a float.
Data type:
|
float, XML-Attribut,
unique
|
Supported:
|
mandatory
|
Compatibility:
|
all
|
cookml
: recipe :
part
: ingredient : unit
Unit of the ingredient
The
unit of the ingredient description. To ensure that recipes can easier
be exchanged internationaly, it is not allowd to use nationaly
accepted units, only american units defined in the following chapter
are allowed "Permitted units".
These units are based on the quasi-standard “Meal-Master.
Data type:
|
string, XML-Attribut,
unique
|
Supported:
|
mandatory
|
Compatibility:
|
all
|
cookml
: recipe :
part
: ingredient : item
Name of the ingredient
The name of
the ingredient. Only the name is to be entered here, no description
(which is to be entered in “ingredient:inote”). Therefore
instead of entering “Finely chopped onions” you are to
only enter “Onions” and in the “ingredient:inote”
you enter “finely chopped”
Data type:
|
string, XML-Attribut,
unique
|
Supported:
|
mandatory
|
Compatibility:
|
all
|
cookml
: recipe : part
: ingredient : inote
Additional description to the ingredient
See
“ingredient:item” for the description.
Data type:
|
string, XML-Element
from head, sequence
|
Supported:
|
mandatory
|
Compatibility:
|
all
|
cookml
: recipe : part
: ingredient : bls
The approriate BLS-Code for the
ingredient
The BLS-key which corresponds to the ingredient or
comes closest. By assigning a BLS-key to an ingredient it is possible
to calculate the substances of the recipe.
Important: Even so your program does not
support BLS you have to pass on the BLS information in your
Import/Export routines.
Data type:
|
string, XML-Attribut,
unique
|
Supported:
|
Support is optional,
however you have to pass data through.
|
Compatibility:
|
Ambrosia, Kalorio
|
cookml
: recipe : part
: ingredient : gram
Approximate value in gram for units which
are not directly convertible
Some units can not be converted
directly. For a calculation of nutritients when using the BLS-code
(Bundelebensmittelschlüssel) it is necessary to have a value in
gram, which can be entered here. It allows you to define for example
for an ingredient “1 package vanille pouder” that it is
30 gram, having done this ones, during the recipe creation or when
changing it, that any time later you can calculate the nutritients of
the recipe.
Data type:
|
non negative integer,
XML-Attribut, unique
|
Supported:
|
Support is optional,
however you have to pass data through.
|
Kompatibiltät:
|
Ambrosia, Kalorio
|
cookml
: recipe : part
: ingredient : shop
Flag, should ingredient be included in
shopping list
If this is “false” then ingredient
should not be included in shopping list, is it “true” or
missing then ingredient should be included in list.
Data type:
|
bool ("true"
oder "false"), XML-Attribut, unique
|
Supported:
|
optional
|
Compatibility:
|
Kalorio
|
cookml
: recipe :
part
: ingredient : calc
Flag, should ingredient be included in
nutrient calculation
When calculating the nutrient values
there are always ingredients which should not be included (e.g. the
oil for a friteuse), if this element is set to “N” then
the ingredient will be ignored, if it is set to “Y” or
not present then the ingredient will be included in the calculation.
Data type:
|
string, XML-Attribut,
unique
|
Supported:
|
Support is optional,
however you have to pass data through.
|
Compatibility:
|
Kalorio
|
cookml
: recipe : part
: ingredient : ridlink
RID of a recipe that is used as an
ingredient
Many recipes require an ingredient which in itself
is a recipe (a base sauce, a dough, etc). In this case one can define
here a “rid” which links to the recipe.
Data type:
|
string, XML-Attribut,
unique
|
Supported:
|
optional
|
Compatibility:
|
|
cookml
: recipe :
part
: ingredient : preparation
Preparation instructions for the
ingredient
Sometimes recipes are recorded/entered with
preparation instruction text being linked with the ingredient. An
excample could be “100 g butter melted down in a pot”,
“200 g onions steamed in it until transparent”.
These should be entered here, however as this
tag is optional and not all programs support it it is necessary to
duplicate these instructions in cookml:recipe:preparation:text.
Data type:
|
string, XML-Attribut,
unique
|
Supported:
|
optional
|
cookml
: recipe : preparation
Preparation instructions for recipe
This
element encloses all instruction steps, there are two variations:
All the preparation instructions are
entered in the tag “text” as a block of text with
paragraphs etc.
Each prepartion step is enclosed in its
own tag “step”. One can have an unlimited number of
preparation steps.
This element is defined as a “choice”,
so you are allowed to include one or the other variation for a
recipe, but you are not allowed to mix and match them for the same
recipe.
Data type:
|
string, XML-Element,
unique, choice
|
Supported:
|
mandatory
|
Compatibility:
|
all
|
cookml
: recipe : preparation
: text
Preparation instructions as a text block
See
description under "preparation"
Data type:
|
string, XML-Element,
unique
|
Supported:
|
mandatory
|
Compatibility:
|
all
|
cookml
: recipe : preparation
: step
Preparation instructions as steps
See
description under "preparation"
Data type:
|
string, XML-Element,
unique
|
Supported:
|
mandatory
|
Compatibility:
|
all
|
cookml
: recipe : remark
Remarks of a user
In each “remark”
element can a user include specific remarks to the recipe.
Data type:
|
complex type,
XML-Element, sequence
|
Supported:
|
optional
|
Compatibility:
|
|
cookml
: recipe :
remark
: user
The name of the user of the remark
Used
to record the name of the user having made the remark.
Data type:
|
string, XML-Attribut,
unique
|
Supported:
|
optional
|
Compatibility:
|
Kalorio
|
cookml : recipe
:
remark : line
A short remark
Enter here a short
remark
Data type:
|
string, XML-Element,
sequence
|
Supported:
|
optional
|
Compatibility:
|
Ambrosia, Kalorio
|
cookml
: menu
The start of a menu
Besides recipes
cookML supports also the transfer of menus. A menu definition is a
list of recipes, which are defined externaly. The recipes has to be
included in the same file, however only in the cookml:recipe root
element and not as part of the menu.
Data type:
|
complex type,
XML-Element, sequence
|
Supported:
|
optional
|
Compatibility:
|
Ambrosia
|
cookml
: menu :
title
Name of the menu
Each menu has to
have a nice name to be able to sell it, this is were it is recorded.
Data type:
|
string, XML-Attribut,
unique
|
Supported:
|
optional
|
Compatibility:
|
Ambrosia
|
cookml
: menu : mcustom
Custom element definiton
This tag
allows to include any type of information not currently supported by
CookML. Keep in mind that this information will not be processed by
other programs and one should not use this extensively, instead you
should contact the author and request an enhancement/inclusion into
the CookML standard for the type of information you want to pass on
using the tag.
"custom" is made up of the attributes
"name", "datatype" and "value", which
should all be self explanatory.
Data type:
|
string, XML-Element,
sequence
|
Supported:
|
optional
|
Compatibility:
|
Ambrosia
|
cookml
: menu : mcustom
: name
Name of the custom field
Description
see "cookml:recipe:mcustom"
Data type:
|
string, XML-Attribut
|
Supported:
|
mandatory
|
Compatibility:
|
Ambrosia
|
cookml
: menu : mcustom
: datatype
Data type of the custom field
Description
see "cookml:recipe:mcustom"
Data
type:
|
string,
XML-Attribut
|
Supported:
|
mandatory
|
Compatibility:
|
Ambrosia
|
cookml
: menu : mcustom
: value
Value of a custom field
Description
see "cookml:recipe:mcustom"
Data type:
|
string, XML-Attribut
|
Supported:
|
mandatory
|
Compatibility:
|
Ambrosia
|
cookml
: menu :
mrecipe
Recipe of a menu
Here you can define
a recipe after the other to create a menu.
Important: All recipes
listed in a menu have to be included in the same CML instance file,
otherwise it is will happen to often that a recipe is not available
when importing the CML instance.
Data type:
|
complex type,
XML-Element, sequence
|
Supported:
|
optional
|
Compatibility:
|
Ambrosia
|
cookml
: menu :
mrecipe
: amount
Quantity of recipe
The quantity
defined here defines how much of the recipe should be prepared for
this menu. The unit is as per the definition of the recipe.
Data type:
|
string, XML-Attribut,
unique
|
Supported:
|
optional
|
Compatibility:
|
Ambrosia
|
cookml
: menu :
mrecipe
: persons
Number of persons to be served
This
defines the number of persons for which this menu item is to be
served.
Data type:
|
string, XML-Attribut,
unique
|
Supported:
|
optional
|
Compatibility:
|
|
cookml
: menu :
mrecipe
: rid
Recipe “rid” of the menu item
A
menu structure does not include recipe data, a recipe is just linked
to using recipe:RID.
Data type:
|
string, XML-Attribut,
unique
|
Supported:
|
optional
|
Compatibility:
|
|
cookml
: menu :
mrecipe
:title
Name of the recipe item
Just to
double up, here the title of recipe, just in case that the “rid”
is not found.
Data type:
|
string, XML-Attribut,
unique
|
Supported:
|
optional
|
Compatibility:
|
Ambrosia
|
cookml
: menu : mrecipe
: desc
Description of the menu item
You can
define here a description of the recipe which is better adapted to
the particular position of it in the menu or to provide further
details on it.
Data type:
|
string, XML-Element,
sequence
|
Supported:
|
optional
|
Compatibility:
|
Ambrosia
|
Encoding used:
CML files have to be encoded using the UTF-8
character set.
UTF-8 is the simpliest form of Unicode:
Each ASCII character with a value of <127
ASCII is still used as the ASCII character.
Special characters with a value of >127
ASCII will be encoded as 16-bit Unicode (2 bytes per character)
Most libraries/development tools will do
this encoding for you, however should you have to program this
yourself following a translation chart.
Ä (0xC384)
|
ä (0xC3A4)
|
À (0xC380)
|
à (0xC3A0)
|
Á (0xC381)
|
á (0xC3A1)
|
 (0xC382)
|
â (0xC3A2)
|
à (0xC383)
|
ã (0xC3A3)
|
|
|
È (0xC388)
|
è (0xC3A8)
|
É (0xC389)
|
é (0xC3A9)
|
Ê (0xC38A)
|
ê (0xC3AA)
|
Ë (0xC38B)
|
ë (0xC3AB)
|
|
|
Ì (0xC38C)
|
ì (0xC3AC)
|
Í (0xC38D)
|
í (0xC3AD)
|
Î (0xC38E)
|
î (0xC3AE)
|
Ï (0xC38F)
|
ï (0xC3AF)
|
Ö (0xC396)
|
ö (0xC3B6)
|
Ò (0xC392)
|
ò (0xC3B2)
|
Ó (0xC393)
|
ó (0xC3B3)
|
Ô (0xC394)
|
ô (0xC3B4)
|
Õ (0xC395)
|
õ (0xC3B5)
|
Ü (0xC39C)
|
ü (0xC3BC)
|
Ù (0xC399)
|
ù (0xC3B9)
|
Ú (0xC39A)
|
ú (0xC3BA)
|
Û (0xC39B)
|
û (0xC3BB)
|
|
|
ß (0xC39F)
|
Æ (0xC386)
|
æ (0xC3A6)
|
Ç (0xC387)
|
ç (0xC3A7)
|
Ñ (0xC391)
|
ñ (0xC3B1)
|
|
|
|
° (0xC2B0)
|
© (0xC2A9)
|
¼ (0xC2BC)
|
½ (0xC2BD)
|
¾ (0xC2BE)
|
ø (0xC3B8)
|
|
|
|
|
Construction of the recipe id
(rid):
The recide id (rid) has to be constructed
always in the same way. Here we use the ID structure from Rolf
Wilhelm, which he used in his recipe program Ambrosia, which has
found general acceptance.
The cookML recipe ID is made up of two 32 bit
values.
Value 1:
Coded date Bit 0-30
|
3
|
2
|
1
|
0
|
|
Bit
|
1
|
0
|
9
|
8
|
7
|
6
|
5
|
4
|
3
|
2
|
1
|
0
|
9
|
8
|
7
|
6
|
5
|
4
|
3
|
2
|
1
|
0
|
9
|
8
|
7
|
6
|
5
|
4
|
3
|
2
|
1
|
0
|
|
|
-
|
year - 1980 (11 bits)
|
month (4 bits)
|
days (5 bits)
|
hours (5 bits)
|
minutes (6 bits)
|
|
example
|
12:09, 16-09-2006
|
0
|
0
|
0
|
0
|
0
|
0
|
0
|
1
|
1
|
0
|
1
|
0
|
1
|
0
|
0
|
1
|
1
|
0
|
0
|
0
|
0
|
0
|
1
|
1
|
0
|
0
|
0
|
0
|
1
|
0
|
0
|
1
|
= 27886345
|
Value 2:
|
3
|
2
|
1
|
0
|
|
Bit
|
1
|
0
|
9
|
8
|
7
|
6
|
5
|
4
|
3
|
2
|
1
|
0
|
9
|
8
|
7
|
6
|
5
|
4
|
3
|
2
|
1
|
0
|
9
|
8
|
7
|
6
|
5
|
4
|
3
|
2
|
1
|
0
|
|
|
creator ID (12 bits)
|
serial ID (20 bits)
|
|
example
|
creator id 70, serial 783150
|
0
|
0
|
0
|
0
|
0
|
1
|
0
|
0
|
0
|
1
|
1
|
0
|
1
|
0
|
1
|
1
|
1
|
1
|
1
|
1
|
0
|
0
|
1
|
1
|
0
|
0
|
1
|
0
|
1
|
1
|
1
|
0
|
= 74183470
|
Creator-ID:
The systems user name
(login name) is summed up in the following way:
For each character
(in upper case): Creator-ID += Ascii(character) *
character-position
Character-position: 1-n
|
W
|
B
|
R
|
U
|
H
|
I
|
N
|
|
ordinal value
|
87
|
66
|
82
|
85
|
72
|
73
|
78
|
|
*
|
|
position
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
|
=
|
|
|
87
|
132
|
246
|
340
|
360
|
438
|
546
|
= 2149
|
As over runs are ignored, and the user name
is converted to upper case for this calculation the final result is:
101
Serial-ID:
Starting with a random number which is
increased by 1 (if multiple serial id's are generated at once), any
over runs are ignored.
Updating a RID:
If an object
(recipe) has a valid “RID” one updates only the date
portion, the Serial-ID and the Creator-ID will never be changed.
This is a change compared to the first version
of cookML!
Following some example code (maybe these should
be kept in a files and just be linked from here????).
Here is the implementation from Ralf Wilhelm in
VB:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "ClFingerprint"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
Private Type TBinFingerprint '
binary type (db storage only)
FP1 As Long
FP2 As Long
End Type
Private Type TFingerprint '
decoded type (analyseable version)
Datum As Date
CreatorID As Long
Counter As Long
End Type
Dim IsInitialised As Boolean
Dim fp As TFingerprint, fpbin As
TBinFingerprint
Dim UserNameString As String
Sub UpdateFingerprint(Optional ByVal
Userid As String = "", Optional ByVal Datum As Date = 0)
DoInitialize
If Datum = 0 Then Datum = Now
fp.Datum = Datum
If Len(Userid) > 0 Then
fp.CreatorID = GetFingerprintAktCreator(Userid)
Convert2Bin
End Sub
Property Let FP1(ByVal FP1 As Long)
IsInitialised = True
fpbin.FP1 = FP1
Convert2Data
End Property
Property Let FP2(ByVal FP2 As Long)
IsInitialised = True
fpbin.FP2 = FP2
Convert2Data
End Property
Property Get FP1() As Long
DoInitialize
FP1 = fpbin.FP1
End Property
Property Get FP2() As Long
DoInitialize
FP2 = fpbin.FP2
End Property
Property Let CreatorID(ByVal ID As
Long)
IsInitialised = True
fp.CreatorID = ID
Convert2Bin
End Property
Property Get CreatorID() As Long
DoInitialize
CreatorID = fp.CreatorID
End Property
Property Let Datum(ByVal d As Date)
IsInitialised = True
fp.Datum = d
Convert2Bin
End Property
Property Get Datum() As Date
DoInitialize
Datum = fp.Datum
End Property
Property Let Serial(ByVal Serial As
Long)
IsInitialised = True
fp.Counter = Serial
Convert2Bin
End Property
Property Get Serial() As Long
DoInitialize
Serial = fp.Counter
End Property
Sub Update()
If Not IsInitialised Or
fp.CreatorID = 0 Or fp.Counter = 0 Then
IsInitialised = False
DoInitialize
End If
IsInitialised = True
fp.Datum = Now
Convert2Bin
End Sub
Sub Convert2Data()
Dim Y As Long, d As Long, m As
Long, H As Long, mi As Long
With fpbin
Y = 1980 + ((.FP1 And
&HFFF00000) / (2 ^ 20))
m = ((.FP1 And &HF0000) / (2
^ 16))
d = ((CLng(.FP1) And &HF800&)
/ (2 ^ 11))
H = ((.FP1 / (2 ^ 6)) And &H1F)
mi = (.FP1 And &H3F)
fp.Datum = DateSerial(Y, m, d) +
TimeSerial(H, mi, 0)
fp.CreatorID = (Abs(.FP2) \ (2&
^ 20)) And &H7FF
If .FP2 < 0 Then fp.CreatorID
= fp.CreatorID + 2048
fp.Counter = (Abs(.FP2) And
&HFFFFF)
'Debug.Print "FP de:";
FP.Datum, FP.CreatorID, FP.Counter, "("; .FP1; .fp2; ")"
End With
If fpbin.FP1 = 0 And fpbin.FP2 = 0
Then IsInitialised = False
End Sub
Sub Convert2Bin()
Dim Y As Long
With fp
Y = Year(.Datum) - 1980
fpbin.FP1 = (Y * (2& ^ 20))
+ _
(Month(.Datum) * (2
^ 16)) + _
(Day(.Datum) * (2 ^
11)) + _
(Hour(.Datum) * (2 ^
6)) + _
Minute(.Datum)
fpbin.FP2 = ((.CreatorID And
&H7FF) * (2& ^ 20)) + _
(.Counter And
&HFFFFF)
If .CreatorID > 2047 Then
fpbin.FP2 = -fpbin.FP2
' Debug.Print "FP en:";
FP.Datum, FP.CreatorID, FP.Counter, "("; FPBin.FP1;
FPBin.fp2; ")"
End With
End Sub
Function CompareFingerprint(ByVal
FPBIN1 As Long, ByVal FPBIN2 As Long) As Long
' Ergebnis:
' 0 = Identisch
'-1 = FP1 älter wie FP2
'+1 = FP2 jünger wie FP2
'-2 = unterschiedliche Objekte, aber
Objekt 1 ist älter wie Objekt 2
'+2 = unterschiedliche Objekte, aber
Objekt 1 ist jünger wie Objekt 2
Dim ObjectID As Long
Dim FPB2 As TBinFingerprint
Dim a As String, i As Long
FPB2.FP1 = FPBIN1
FPB2.FP2 = FPBIN2
' Gleichheit schneller auf binärer
Ebene klären ...
If fpbin.FP1 = FPB2.FP1 And
fpbin.FP2 = FPB2.FP2 Then
CompareFingerprint = 0
Else
ObjectID = 1
If fpbin.FP2 <> FPB2.FP2
Then
ObjectID = 2 ' es liegen
verschiedene Objekte vor !
End If
i = Sgn(fpbin.FP1 - FPB2.FP1) *
ObjectID
If fpbin.FP1 = 0 And FPB2.FP2 <>
0 Then i = 1 * ObjectID
If FPB2.FP1 = 0 And fpbin.FP1 <>
0 Then i = -1 * ObjectID
CompareFingerprint = i
End If
End Function
Property Get
FingerprintInfoTextCRLF() As String
FingerprintInfoTextCRLF =
GetFingerprintInfoText(True)
End Property
Property Get FingerprintInfoText()
As String
FingerprintInfoText =
GetFingerprintInfoText(False)
End Property
Private Function
GetFingerprintInfoText(ByVal IncludeCRLF As Boolean) As String
Dim a As String, crlf As String
crlf = Switch(IncludeCRLF, vbCrLf,
True, " ")
If fp.CreatorID = 0 And fp.Counter
= 0 Then
a = ResolveResString(609)
Else
a = Switch(IncludeCRLF,
ResolveResString(610) & crlf & ResolveResString(611),
True, ResolveResString(612)) & _
fp.Datum &
ResolveResString(613) & Format$(fp.Counter, "000,000")
& ")." & crlf & _
ResolveResString(614)
If fp.CreatorID <>
GetFingerprintAktCreator Then a = a & ResolveResString(615)
a = a &
ResolveResString(616)
End If
GetFingerprintInfoText = a
End Function
Private Sub Class_Initialize()
IsInitialised = False
End Sub
Private Sub DoInitialize()
If Not IsInitialised Then
IsInitialised = True
With fp
.Datum = Now
If EditLastFPCounter = 0 Then
Randomize CLng(CDbl(Now -
CLng(Now)) * 10000&)
EditLastFPCounter = Rnd *
&HFFFFF
End If
EditLastFPCounter =
((EditLastFPCounter + 1) And &HFFFFF)
.Counter = EditLastFPCounter
.CreatorID =
GetFingerprintAktCreator And &H7FF
End With
Convert2Bin
End If
End Sub
Sub Initialize()
IsInitialised = False
DoInitialize
End Sub
Function GetWinuserid() As String
Dim i As Long
If Len(UserNameString) = 0 Then
UserNameString = Space$(64)
If GetUserName(UserNameString,
63) Then
i = InStr(UserNameString,
Chr$(0))
If i > 0 Then
UserNameString = Left$(UserNameString, i - 1)
End If
UserNameString =
UCase$(UserNameString)
End If
GetWinuserid = UserNameString
End Function
Public Function
GetFingerprintAktCreator(Optional ByVal UserIDX As String = "",
Optional ByVal OldModeUser As Boolean = False) As Long
Static LastUI As Long
Dim Userid As String
Dim i As Long, tempui As Long
If Len(UserIDX) Then
UserIDX = UCase$(UserIDX)
tempui = 0
For i = 1 To Len(UserIDX)
tempui = tempui +
(Asc(Mid$(UserIDX, i, 1)) * i)
Next i
If Not OldModeUser Then tempui =
tempui And &HFFF
ElseIf LastUI = 0 Then
Userid = GetWinuserid()
LastUI = 0
For i = 1 To Len(Userid)
LastUI = LastUI +
(Asc(Mid$(Userid, i, 1)) * i)
Next i
If Not OldModeUser Then LastUI =
LastUI And &HFFF
tempui = LastUI
Else
tempui = LastUI
End If
GetFingerprintAktCreator = tempui
End Function
Property Get Winuserid() As String
Winuserid = GetWinuserid()
End Property
Function InfotextAndSource(ByVal
Source As Long, ByVal IDate As Date) As String
Dim a As String
Dim Erg As String
Erg = ""
If fpbin.FP2 = 0 Then
'
Else
Erg = Me.FingerprintInfoText()
End If
a = ""
If Source = 0 Then
a = ResolveResString(710)
ElseIf Source = 1 Then
a = ResolveResString(711)
Else
Select Case Source
'2=MM Text-Import, 3=MM
Base-Import, 4=MasterCook, 5=..., 6=CookML
Case 2: a =
ResolveResString(712)
Case 3: a =
ResolveResString(713)
Case 4: a =
ResolveResString(714)
Case 5: a =
ResolveResString(715)
Case 6: a =
ResolveResString(730)
End Select
a = ResolveResString(716) &
IDate & ResolveResString(717) & a &
ResolveResString(718)
End If
If Len(a) Then Erg = Erg &
vbCrLf & a
InfotextAndSource = Erg
End Function
|
And here an example in Python with some test output from Werner
Bruhin.
import wx
import datetime
import math
import random
def GenerateRID():
# first part, the date
rdate = datetime.datetime.now()
print 'input date: %s' % rdate
datebin = int(((rdate.year -
1980) * math.pow(2, 20)) + \
(rdate.month *
math.pow(2, 16)) + \
(rdate.day *
math.pow(2, 11)) + \
(rdate.hour *
math.pow(2, 6)) + \
rdate.minute)
# second part, creator id and
serial id
uid = wx.GetUserId()
## uid =
'letstrywithareallylongone' # test for a longer id
uid = 'wbruhin'
print 'input user id: %s' %uid
# creator id calculation
uidBin = int(0)
for x in range(len(uid)):
cval = ord(uid[x].upper()) *
(x+1)
## print 'char calc: %s, ord:
%s, value: %s' % (uid[x].upper(), ord(uid[x].upper()), cval)
uidBin += cval
print 'creator id before cut
off: %s' % uidBin
uidBin = uidBin & 0xff
print 'creator id: %s' % uidBin
# serial id
serial = random.randint(0,
999999)
print 'serial id: %s' % serial
part2 = int(((uidBin &
0x7ff) * math.pow(2, 20)) + (serial & 0xfffff))
if uidBin > 2047:
part2 = - part2
return '%s, %s' % (datebin,
part2)
def DecodeRID(rid):
p1, p2 = rid.split(',')
datebin = int(p1)
part2 = int(p2)
# decode the date part
y = int(1980 + ((datebin &
0xfff00000) / math.pow(2, 20)))
m = int(((datebin & 0xf0000)
/ math.pow(2, 16)))
d = int(((datebin & 0xf800)
/ math.pow(2, 11)))
h = int((datebin / math.pow(2,
6))) & 0x1f
min = int(datebin) & 0x3f
rdate = datetime.datetime(y, m,
d, h, min)
# decode part 2
if part2 < 0:
uid = int((part2) /
math.pow(2, 20)) & 0x7ff
uid += 2048
serial = int(-part2) &
0xfffff
else:
uid = int((part2) /
math.pow(2, 20)) & 0x7ff
serial = int(part2) &
0xfffff
return (rdate, uid, serial)
# get a rid
rid = GenerateRID()
print 'generated rid: %s' % rid
print '--------------'
# decode the rid
rdate, uid, serial = DecodeRID(rid)
print 'decoded date: %s' % rdate
print 'decoded uid: %s' % uid
print 'decoded serial: %s' % serial
|
It will produce the following result when running it (obviously
the date would change):
input
date: 2007-12-27 13:19:30.113000
input
user id: wbruhin
creator
id before cut off: 2149
creator
id: 101
serial
id: 637108
generated
rid: 29154131, 106543284
--------------
decoded
date: 2007-12-27 13:19:00
decoded
uid: 101
decoded
serial: 637108
Permited units for ingredients
CookML is an international format. Due to this
all units have to use the american format detailed below and if
necessary have to do the required conversion.
The following list
shows on the left the permitted units and on the right the
approximate German equivalent.
The list is based on the units used by the
Mealmaster standard, this should facilitat the exchange of recipes
with that format.
fl fluid ounce
|
~ 30 ml
|
x per serving
|
pro Portion
|
c cup
|
= 250 ml
|
sm small
|
klein
|
pt pint
|
1/2 Liter
|
md medium
|
mittel
|
qt quart
|
1 Liter
|
lg large
|
gross
|
ga gallon
|
4 Liter
|
cn can
|
Dose
|
oz ounce
|
~ 30 g
|
pk package
|
Packung
|
lb pound
|
~ 450 g
|
pn pinch
|
Prise, Msp.
|
ml milliliter
|
ccm
|
cb cubic cm
|
ccm
|
dr drop
|
Tropfen
|
ds dash
|
Schuss, Spur
|
cl centiliter
|
10 ccm
|
ct carton
|
Karton
|
dc deciliter
|
100 ccm = 0,1 Liter
|
bn bunch
|
Bund
|
l liter
|
Liter
|
sl slice
|
Scheibe
|
mg milligram
|
Milligramm
|
ea each
|
pro Portion
|
cg centigram
|
1/100 Gramm
|
t teaspoon
|
Teeloeffel
|
dg decigram
|
1/10 Gramm
|
ts teaspoon
|
Teeloeffel
|
g gram
|
Gramm
|
T tablespoon
|
Essloeffel
|
tb tablespoon
|
Essloeffel
|
kg kilogram
|
Kilogramm
|
Zurück zum Seitenanfang