diff --git a/_tutorials-BA/100_structure/100_Structure.md b/_tutorials-BA/100_structure/100_Structure.md
new file mode 100644
index 00000000..2a235be3
--- /dev/null
+++ b/_tutorials-BA/100_structure/100_Structure.md
@@ -0,0 +1,7 @@
+---
+layout: tutorials
+type: tutorial
+name: "BEGINNERS: XML basics and minimal MEI structure"
+fullname: "A short tutorial about the basics of XML & MEI"
+data: "100_structure.json"
+---
diff --git a/_tutorials-BA/100_structure/100_structure.json b/_tutorials-BA/100_structure/100_structure.json
new file mode 100644
index 00000000..48740ebb
--- /dev/null
+++ b/_tutorials-BA/100_structure/100_structure.json
@@ -0,0 +1,81 @@
+{
+ "steps": [
+ {
+ "label":"Welcome to MEI",
+ "descFile": "100_structure_step-00-desc.html"
+ },
+ {
+ "label": "The MEI root element",
+ "editorLines": 1,
+ "descFile": "100_structure_step-01-desc.html",
+ "prefillFile": "100_structure_step-01-prefill.xml",
+ "xmlFile": "100_structure_step-01.xml",
+ "xpaths": [
+ {"rule": "count(//mei) = 1", "renderanyway": true, "hint": "You need one mei element."}
+ ]
+ },
+ {
+ "label": "The MEI namespace",
+ "editorLines": 1,
+ "descFile": "100_structure_step-02-desc.html",
+ "prefillFile": "100_structure_step-02-prefill.xml",
+ "xmlFile": "100_structure_step-02.xml",
+ "xpaths": [
+ {"rule": "count(*[local-name()='mei']) = 1", "renderanyway": true, "hint": "You need one mei element."},
+ {"rule": "*[local-name()='mei' and namespace-uri()='http://www.music-encoding.org/ns/mei']", "renderanyway": true, "hint": "You need a @xmlns declaration with the mei namespace 'http://www.music-encoding.org/ns/mei'."}
+ ]
+ },
+ {
+ "label": "Two basic child elements",
+ "editorLines": 4,
+ "descFile": "100_structure_step-03-desc.html",
+ "prefillFile": "100_structure_step-03-prefill.xml",
+ "xmlFile": "100_structure_step-03.xml",
+ "xpaths": [
+ {"rule": "count(//*[local-name()='mei']) = 1", "renderanyway": false, "hint": "You need one mei element."},
+ {"rule": "*[local-name()='mei' and namespace-uri()='http://www.music-encoding.org/ns/mei']", "renderanyway": true, "hint": "You need a @xmlns declaration with the mei namespace 'http://www.music-encoding.org/ns/mei' in the mei element."},
+ {"rule": "count(//*[local-name()='meiHead']) = 1", "renderanyway": false, "hint": "You need one meiHead element."},
+ {"rule": "//*[local-name()='mei']/*[local-name()='meiHead']", "renderanyway": false, "hint": "meiHead has to a be child of the mei element."},
+ {"rule": "count(//*[local-name()='music']) = 1", "renderanyway": false, "hint": "You need one music element."},
+ {"rule": "//*[local-name()='mei']/*[local-name()='music']", "renderanyway": false, "hint": "music has to a be child of the mei element."},
+ {"rule": "//*[local-name()='mei']/*[local-name()='meiHead']/following-sibling::*[local-name()='music']", "renderanyway": false, "hint": "music has to follow the meiHead element."}
+ ]
+ },
+ {
+ "label": "The minimum MEI header",
+ "editorLines": 11,
+ "descFile": "100_structure_step-04-desc.html",
+ "prefillFile": "100_structure_step-04-prefill.xml",
+ "xmlFile": "100_structure_step-04.xml",
+ "xpaths": [
+ {"rule": "count(//*[local-name()='mei']) = 1", "renderanyway": false, "hint": "You need one mei element."},
+ {"rule": "*[local-name()='mei' and namespace-uri()='http://www.music-encoding.org/ns/mei']", "renderanyway": true, "hint": "You need a @xmlns declaration with the mei namespace 'http://www.music-encoding.org/ns/mei' in the mei element."},
+ {"rule": "count(//*[local-name()='meiHead']) = 1", "renderanyway": false, "hint": "You need one meiHead element."},
+ {"rule": "//*[local-name()='mei']/*[local-name()='meiHead']", "renderanyway": false, "hint": "meiHead has to be a child of the mei element."},
+ {"rule": "count(//*[local-name()='music']) = 1", "renderanyway": false, "hint": "You need one music element."},
+ {"rule": "//*[local-name()='mei']/*[local-name()='music']", "renderanyway": false, "hint": "music has to be a child of the mei element."},
+ {"rule": "//*[local-name()='mei']/*[local-name()='meiHead']/following-sibling::*[local-name()='music']", "renderanyway": false, "hint": "music has to follow the meiHead element."},
+ {"rule": "count(//*[local-name()='fileDesc']) = 1", "renderanyway": false, "hint": "You need one fileDesc element."},
+ {"rule": "//*[local-name()='meiHead']/*[local-name()='fileDesc']", "renderanyway": false, "hint": "fileDesc has to be a child of the meiHead element."},
+ {"rule": "count(//*[local-name()='titleStmt']) = 1", "renderanyway": false, "hint": "You need one titleStmt element."},
+ {"rule": "//*[local-name()='fileDesc']/*[local-name()='titleStmt']", "renderanyway": false, "hint": "titleStmt has to be a child of the fileDesc element."},
+ {"rule": "count(//*[local-name()='pubStmt']) = 1", "renderanyway": false, "hint": "You need one pubStmt element."},
+ {"rule": "//*[local-name()='fileDesc']/*[local-name()='pubStmt']", "renderanyway": false, "hint": "pubStmt has to be a child of the fileDesc element."},
+ {"rule": "//*[local-name()='fileDesc']/*[local-name()='titleStmt']/following-sibling::*[local-name()='pubStmt']", "renderanyway": false, "hint": "pubStmt has to follow the titleStmt element."},
+ {"rule": "count(//*[local-name()='title']) = 1", "renderanyway": false, "hint": "You need one title element."},
+ {"rule": "//*[local-name()='titleStmt']/*[local-name()='title']", "renderanyway": false, "hint": "title has to be a child of the titleStmt element."}
+ ]
+ }
+ ],
+ "end": "100_structure_end.html",
+ "resp":[
+ {
+ "name":"Stefan Münnich",
+ "affiliation":"Anton Webern Gesamtausgabe | University of Basel"
+ },
+ {
+ "name":"Johannes Kepper",
+ "affiliation":"Beethovens Werkstatt | Universität Paderborn"
+ }
+ ]
+}
diff --git a/_tutorials-BA/100_structure/100_structure_end.html b/_tutorials-BA/100_structure/100_structure_end.html
new file mode 100644
index 00000000..221cdb93
--- /dev/null
+++ b/_tutorials-BA/100_structure/100_structure_end.html
@@ -0,0 +1,31 @@
+
+
Congratulations!
+
+ You have just written a valid MEI file and successfully finished this tutorial. You should be able now
+
+
to understand the basic principles of XML and how it is the basis for MEI
+
to identify and to write the outermost basic structure of an MEI-conformant document
+ including its title
+
to differentiate between two main sections of a MEI file responsible for metadata information
+ (<meiHead>) or information about the musical content (<music>).
+
+
+ Since the topics addressed in this tutorial referred to the chapter Structural Elements of the MEI Guidelines,
+ we recommend to consult this chapter whenever you need more detailed information.
+
+
+ Of course, a lot more is needed for a comprehensive MEI file – we left out all information about any musical
+ content like measures, staves, or notes, and you also need to learn how to set up meter, key, and clefs.
+ Here are some other tutorials we would like to recommend as next steps with MEI. Of course, you can always come
+ back to these (or even this one) when you would like to remind yourself how to do certain things in MEI.
+
+
+ As soon as you have familiarized yourself with MEI to some degree, we invite you to share your
+ experience with the MEI Community
+ and write a tutorial on an aspect of MEI that you're particularly interested in. You don't have to be an expert
+ for this – it's good to have tutorials on different levels, and very often a tutorial written by other beginners
+ which just mastered a task is easier to follow than a guide written by someone who's not seeing the problem at all.
+ We do have a tutorial on how to write tutorials,
+ and there are templates to follow. It's that easy to become an active member of the MEI Community :-)
+
+
diff --git a/_tutorials-BA/100_structure/step-00/100_structure_step-00-desc.html b/_tutorials-BA/100_structure/step-00/100_structure_step-00-desc.html
new file mode 100644
index 00000000..6936d114
--- /dev/null
+++ b/_tutorials-BA/100_structure/step-00/100_structure_step-00-desc.html
@@ -0,0 +1,21 @@
+
+
+ In this tutorial, you will get accustomed with some very basic XML backgrounds and learn about the outermost
+ structure of a valid MEI document. You will learn to identify different parts of an MEI file and which type of
+ information you can expect in which part.
+
+
+ The topics addressed in this tutorial are referring to the chapter Structural Elements of the MEI Guidelines. We recommend to consult this
+ chapter whenever you need more detailed information.
+
+
+ Please be aware that the code you write in this tutorial cannot be immediately rendered because it lacks information
+ about any actual musical content.
+
+
+ However, after you have finished this tutorial, you may want to do other tutorials, which will introduce you to
+ other important aspects of MEI. (Many of them include renderable music encodings.) These tutorials also serve as simple
+ reference to MEI – you can always go back to them.
+
+
In order to get started, please hit the "continue" button on the lower right of this paragraph.
+
diff --git a/_tutorials-BA/100_structure/step-01/100_structure_step-01-desc.html b/_tutorials-BA/100_structure/step-01/100_structure_step-01-desc.html
new file mode 100644
index 00000000..a2ae71e6
--- /dev/null
+++ b/_tutorials-BA/100_structure/step-01/100_structure_step-01-desc.html
@@ -0,0 +1,29 @@
+
+
+ Step one: get accustomed with some very basic XML backgrounds and learn about the root
+ element of MEI.
+
+
+ MEI uses XML to represent music notation. XML is a hierarchical
+ encoding system in which elements are the core objects. They are represented using so called “tags”. Most of the
+ time these tags consist of an opening tag (that is a name enclosed in angle brackets like
+ <element>) and its corresponding closing tag (</element>). If there is no content
+ between these two tags (like text or other elements) the element can be shortened to a so called self-closing
+ tag of the form <element />. In any case, every opened tag must be closed later on.
+
+
+ You can think of an XML document like a tree that branches from one (outer) root element to nested (inner) child
+ elements. The root element is the parent of all other elements. In MEI documents, this root element is called –
+ for obvious reasons – <mei>, but it could have been any arbitrary name.
+
+
+
Enter a <mei> root element in the editor below. Do not forget to close the opening tag by a corresponding closing tag.
+
+
+ PS: We will cover some more basic XML principles in the next steps. For more detailed information consider to have a
+ look at the dozens of materials available on the web, e.g. the
+ Gentle Introduction to XML of the
+ Text Encoding Initative (TEI).
+
+
+
diff --git a/_tutorials-BA/100_structure/step-01/100_structure_step-01-prefill.xml b/_tutorials-BA/100_structure/step-01/100_structure_step-01-prefill.xml
new file mode 100644
index 00000000..44fbfea5
--- /dev/null
+++ b/_tutorials-BA/100_structure/step-01/100_structure_step-01-prefill.xml
@@ -0,0 +1 @@
+
diff --git a/_tutorials-BA/100_structure/step-02/100_structure_step-02-desc.html b/_tutorials-BA/100_structure/step-02/100_structure_step-02-desc.html
new file mode 100644
index 00000000..8315feeb
--- /dev/null
+++ b/_tutorials-BA/100_structure/step-02/100_structure_step-02-desc.html
@@ -0,0 +1,29 @@
+
+
+ Step two: learn about the application and use of namespaces.
+
+
+ Fine! As mentioned in the previous step, the name of the root element of an XML document is basically an arbitrary
+ name that provides no meaning in itself for machine-processing. To make clear in which context an element is
+ defined and to avoid name conflicts with elements, XML makes use of so called
+ namespaces.
+ Namespaces can be declared by adding an @xmlns namespace declaration to the root element.
+
+
+ For example, the MEI namespace is http://www.music-encoding.org/ns/mei and can be declared
+ as follows: xmlns="http://www.music-encoding.org/ns/mei"
+
+
+ Whenever you see an entity with a prepended @-sign in the text (like @xmlns above),
+ this means we refer to an XML attribute. (This kind of reference is common practice and originates in the
+ XPath language.)
+ Attributes contain specified information (attribute values) that are related to elements. However, unlike
+ elements, XML attributes do not have their own opening or closing brackets, but are placed solely inside the
+ opening tag of an element, next to the element's name. They consist of the plain attribute's name connected by
+ an equal sign to an attribute's value which must always be quoted (with single or double quotes). Multiple
+ attributes are separated by blank spaces. Be aware that the @-sign is only prepended in textual
+ descriptions, not in the encoding itself.
+
+
+
In the editor below, add a MEI namespace declaration to the MEI root element.
+
diff --git a/_tutorials-BA/100_structure/step-02/100_structure_step-02-prefill.xml b/_tutorials-BA/100_structure/step-02/100_structure_step-02-prefill.xml
new file mode 100644
index 00000000..3958eccf
--- /dev/null
+++ b/_tutorials-BA/100_structure/step-02/100_structure_step-02-prefill.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/_tutorials-BA/100_structure/step-03/100_structure_step-03-desc.html b/_tutorials-BA/100_structure/step-03/100_structure_step-03-desc.html
new file mode 100644
index 00000000..b63b5e33
--- /dev/null
+++ b/_tutorials-BA/100_structure/step-03/100_structure_step-03-desc.html
@@ -0,0 +1,28 @@
+
+
+ Step three: learn about the main child elements of the <mei> root element: <meiHead>
+ and <music>.
+
+
+ Well done! Now, that we have declared a namespace within our root element, all other elements nested in the root
+ element can be resolved according to the MEI namespace by machine-processing.
+
+ As already mentioned, you can think of an XML document like a tree that branches from one (outer) root element
+ to nested (inner) child elements. A MEI-encoded file contains at least two structures within the
+ <mei> root element:
+
+
+
+ <meiHead> - contains a set of elements that supply metadata related to the MEI encoding, including
+ bibliographic information, responsibility statements, encoding standards, or provenance.
+
+
+ <music> - contains a set of elements that provide for the encoding of the actual musical content.
+ Beside others, it may comprise structural elements to describe the form of a musical piece (sections,
+ movements, document groups), or notational elements, like e.g. notes, rest, articluations, or dynamics.
+
+
+
+
In the editor below, add a <meiHead> and a <music> element inside the
+ <mei> root element.
+
diff --git a/_tutorials-BA/100_structure/step-03/100_structure_step-03-prefill.xml b/_tutorials-BA/100_structure/step-03/100_structure_step-03-prefill.xml
new file mode 100644
index 00000000..f908e5ba
--- /dev/null
+++ b/_tutorials-BA/100_structure/step-03/100_structure_step-03-prefill.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/_tutorials-BA/100_structure/step-04/100_structure_step-04-desc.html b/_tutorials-BA/100_structure/step-04/100_structure_step-04-desc.html
new file mode 100644
index 00000000..40339529
--- /dev/null
+++ b/_tutorials-BA/100_structure/step-04/100_structure_step-04-desc.html
@@ -0,0 +1,26 @@
+
+
+ Step four: provide the minimum necessary information for the MEI header.
+
+
+ Perfect! You are now pretty close to a valid basic MEI file structure. What is missing yet, are two mandatory
+ elements of the MEI header:
+
+
+ <titleStmt> - a container element for title and responsibility meta-data. The title of a
+ bibliographic entity is given via its mandatory sub-element <title>;
+
+
+ <pubStmt> - a container element for information regarding the publication or distribution of a
+ bibliographic item, including the publisher's name and address, the date of publication, and other relevant
+ details.
+
+
+
+ Both these elements are part of the file description (<fileDesc>), which is a direct child element
+ of <meiHead> and provides for a full bibliographic description of a MEI file.
+
+
In the editor below, add a <fileDesc> element inside the given <meiHead>.
+ Then add the mandatory <titleStmt> and <pubStmt> elements to
+ <fileDesc> and a <title> element to <titleStmt>.
You just finished your first tutorial about MEI, and you should be able to encode a very simple melody with
+ MEI already. Of course, a lot more is needed for a complete MEI file – we left out all structural information
+ about measures and staves, and you also need to learn how to set up meter, key, and clefs. As next steps with
+ MEI, we would like to recommend our tutorials on
+ chords or
+ rests.
+ Of course, you can always come back to
+ these (or even this one) when you would like to remind yourself how to do certain things in MEI.
+
As soon as you have familiarized yourself with MEI to some degree, we invite you to share your
+ experience with the MEI Community and write a tutorial on an aspect of MEI that you're particularly
+ interested in. You don't have to be an expert for this – it's good to have tutorials on different levels.
+ Often a tutorial written by other beginners which just mastered a task is easier to follow than
+ a guide written by someone who's not seeing the problem at all. We do have a tutorial on how to write
+ tutorials, and there are templates to follow. It's that easy to become an active member of the MEI Community :-)
+
\ No newline at end of file
diff --git a/_tutorials-BA/101_quickstart/101_quickstart_step-00-desc.html b/_tutorials-BA/101_quickstart/101_quickstart_step-00-desc.html
new file mode 100644
index 00000000..32c1cbe6
--- /dev/null
+++ b/_tutorials-BA/101_quickstart/101_quickstart_step-00-desc.html
@@ -0,0 +1,15 @@
+
+
+ In this tutorial, you will learn how to encode a very simple melody in MEI. You will learn how to describe
+ the most basic aspects of music notation as structured data, so that computers can parse your code.
+
+
+ The code you write will be immediately rendered, and the rendering will respond to your changes. That way,
+ you will get a feeling on how the different parameters interact.
+
+
+ After you have finished this tutorial, you may want to do other tutorials, which will introduce you other
+ important aspects of MEI. These tutorials also serve as simple reference to MEI – you can always go back to them.
+
+
In order to get started, please hit the "continue" button on the lower right of this paragraph.
+
\ No newline at end of file
diff --git a/_tutorials-BA/101_quickstart/step-01/101_quickstart_step-01-desc.html b/_tutorials-BA/101_quickstart/step-01/101_quickstart_step-01-desc.html
new file mode 100644
index 00000000..a8d32b57
--- /dev/null
+++ b/_tutorials-BA/101_quickstart/step-01/101_quickstart_step-01-desc.html
@@ -0,0 +1,25 @@
+
+
In order to encode a note, all relevant information needs to be recorded in machine-readable form. Depending
+ on a project's needs, the selection of what is relevant and what is not may differ, but for the purpose of
+ this introduction, let's agree on the most basic information of a note: It's written pitch and duration. In
+ order to express pitch, MEI uses
+ Scientific Pitch Notation,
+ where the so-called middle-C is expressed as "C4". However, it separates that into two separate pieces of
+ information: The pitch name (in MEI called @pname), and the octave (@oct). This separation has
+ various reasons, which are of no importance here. It is also important to note that pitch names are given as
+ lower-case strings in MEI.
+
The other important information is, of course, duration (@dur). Here, simple integer values are used
+ to indicate the duration of a note. A full note gets a value of 1, a half note needs 2,
+ a quarter 4 and so on.
+
We would like to ask you to enter the following code into the editor box:
+ <note pname="e" oct="4" dur="4"/>. You should then see the note rendered. You may play a little
+ bit with the attribute values to see how they influence the rendering. You will also see hints on how to write the
+ correct code. Whenever you're ready, make sure to have the correct code in the editor, and then hit the "continue"
+ button on the lower right.
+
+ PS: If you're not too familiar with XML: Whenever we refer to attributes, we prepend their name with the @-sign.
+ This is common practice and originates in the XPath
+ language. When writing them in XML, you must not include the @-sign, but write the attribute's name only. Feel
+ free to have a look at our tutorial on XML basics.
+
+
diff --git a/_tutorials-BA/101_quickstart/step-01/101_quickstart_step-01-prefill.xml b/_tutorials-BA/101_quickstart/step-01/101_quickstart_step-01-prefill.xml
new file mode 100644
index 00000000..b28124ba
--- /dev/null
+++ b/_tutorials-BA/101_quickstart/step-01/101_quickstart_step-01-prefill.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/_tutorials-BA/101_quickstart/step-02/101_quickstart_step-02-desc.html b/_tutorials-BA/101_quickstart/step-02/101_quickstart_step-02-desc.html
new file mode 100644
index 00000000..ebeb5bcc
--- /dev/null
+++ b/_tutorials-BA/101_quickstart/step-02/101_quickstart_step-02-desc.html
@@ -0,0 +1,10 @@
+
+
+ Congratulations, you've just encoded your first note in MEI. Now let's continue and add a couple more notes to encode
+ your first simple sequence of notes:
+
+
+
+ Please try to reproduce the sequence above with MEI (you can copy & paste the first note element as needed). Each note needs one @pname, @oct and @dur attribute. Keep in mind that pitch names are given as lower-case strings (ranging from a to g) in MEI.
+
+
diff --git a/_tutorials-BA/101_quickstart/step-03/101_quickstart_step-03-desc.html b/_tutorials-BA/101_quickstart/step-03/101_quickstart_step-03-desc.html
new file mode 100644
index 00000000..67466239
--- /dev/null
+++ b/_tutorials-BA/101_quickstart/step-03/101_quickstart_step-03-desc.html
@@ -0,0 +1,13 @@
+
+
Congratulations, you've just encoded your first sequence of notes in MEI. Now let's adjust some duration values to encode your first simple melody – you certainly know "Mary had a little lamb":
+
+
+ Please try to reproduce the melody above with MEI. Each note needs @pname, @oct and @dur.
+
+
+ Keep in mind that the @dur attribute can have values like "1", "2", "4",
+ "8" or "16" to indicate different rhythmical values.
+ For the first note, you need an additional @dots attribute, where you need to specify
+ the number of dots as an integer – in this case, it's simply a dots="1".
+
+
diff --git a/_tutorials-BA/101_quickstart/step-03/101_quickstart_step-03-prefill.xml b/_tutorials-BA/101_quickstart/step-03/101_quickstart_step-03-prefill.xml
new file mode 100644
index 00000000..441e8481
--- /dev/null
+++ b/_tutorials-BA/101_quickstart/step-03/101_quickstart_step-03-prefill.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/_tutorials-BA/102_incipit/102_incipit.json b/_tutorials-BA/102_incipit/102_incipit.json
new file mode 100644
index 00000000..b5073959
--- /dev/null
+++ b/_tutorials-BA/102_incipit/102_incipit.json
@@ -0,0 +1,524 @@
+{
+ "steps": [
+ {
+ "label": "Score & staff definition",
+ "editorLines": 7,
+ "descFile": "102_incipit_step-01-desc.html",
+ "prefillFile": "102_incipit_step-01-prefill.xml",
+ "xmlFile": "102_incipit_step-01.xml",
+ "xpaths": [
+ {"rule": "count(//mei:scoreDef) = 1", "renderanyway": false, "hint": "You need one scoreDef element."},
+ {"rule": "count(//mei:scoreDef/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the scoreDef element."},
+ {"rule": "count(//mei:staffGrp) = 1", "renderanyway": false, "hint": "You need one staffGrp element."},
+ {"rule": "count(//mei:staffGrp/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the staffGrp element."},
+ {"rule": "//mei:scoreDef/mei:staffGrp", "renderanyway": false, "hint": "staffGrp element has to be a child of scoreDef element."},
+ {"rule": "count(//mei:staffDef) = 1", "renderanyway": false, "hint": "You need one staffDef element."},
+ {"rule": "count(//mei:staffDef/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the staffDef element."},
+ {"rule": "//mei:staffGrp/mei:staffDef", "renderanyway": false, "hint": "staffDef element has to be a child of staffGrp element."}
+ ]
+ },
+ {
+ "label": "Score & staff attributes",
+ "editorLines": 7,
+ "descFile": "102_incipit_step-02-desc.html",
+ "prefillFile": "102_incipit_step-02-prefill.xml",
+ "xmlFile": "102_incipit_step-02.xml",
+ "xpaths": [
+ {"rule": "count(//mei:scoreDef) = 1", "renderanyway": false, "hint": "You need one scoreDef element."},
+ {"rule": "count(//mei:staffGrp) = 1", "renderanyway": false, "hint": "You need one staffGroup element."},
+ {"rule": "count(//mei:staffGrp/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the staffGrp element."},
+ {"rule": "//mei:scoreDef/mei:staffGrp", "renderanyway": false, "hint": "staffGrp element has to be a child of scoreDef element."},
+ {"rule": "count(//mei:staffDef) = 1", "renderanyway": false, "hint": "You need one staffDef element."},
+ {"rule": "//mei:staffGrp/mei:staffDef", "renderanyway": false, "hint": "staffDef element has to be a child of staffGrp element."},
+ {"rule": "count(//mei:scoreDef/@*) = 2", "renderanyway": false, "hint": "You need two attributes on scoreDef (@key.sig & @meter.sym)."},
+ {"rule": "//mei:scoreDef/@key.sig = '3f'", "renderanyway": false, "hint": "You need a @key.sig attribute with a value of 3f."},
+ {"rule": "//mei:scoreDef/@meter.sym = 'cut'", "renderanyway": false, "hint": "You need an @meter.sym attribute with a value of cut."},
+ {"rule": "count(//mei:staffDef/@*) = 4", "renderanyway": false, "hint": "You need four attributes on staffDef (@n, @lines, @clef.shape & @clef.line)."},
+ {"rule": "//mei:staffDef/@n = '1'", "renderanyway": false, "hint": "You need a @n attribute with a value of 1."},
+ {"rule": "//mei:staffDef/@lines = '5'", "renderanyway": false, "hint": "You need a @lines attribute with a value of 5."},
+ {"rule": "//mei:staffDef/@clef.shape = 'G'", "renderanyway": false, "hint": "You need a @clef.shape attribute with a value of G."},
+ {"rule": "//mei:staffDef/@clef.line = '2'", "renderanyway": false, "hint": "You need a @clef.line attribute with a value of 2."}
+ ]
+ },
+ {
+ "label": "Measure, staff & layer",
+ "editorLines": 14,
+ "descFile": "102_incipit_step-03-desc.html",
+ "prefillFile": "102_incipit_step-03-prefill.xml",
+ "xmlFile": "102_incipit_step-03.xml",
+ "xpaths": [
+ {"rule": "count(//mei:section) = 1", "renderanyway": false, "hint": "You need one section element."},
+ {"rule": "count(//mei:section/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the section element."},
+ {"rule": "//mei:score/mei:section", "renderanyway": false, "hint": "section element has to be a child of score element."},
+ {"rule": "count(//mei:measure) = 1", "renderanyway": false, "hint": "You need one measure element."},
+ {"rule": "//mei:section/mei:measure", "renderanyway": false, "hint": "measure element has to be a child of section element."},
+ {"rule": "count(//mei:measure/@*) = 1", "renderanyway": false, "hint": "You need one attribute on measure (@n)."},
+ {"rule": "//mei:measure/@n = '0'", "renderanyway": false, "hint": "You need a @n attribute with a value of 0."},
+ {"rule": "count(//mei:staff) = 1", "renderanyway": false, "hint": "You need one staff element."},
+ {"rule": "//mei:measure/mei:staff", "renderanyway": false, "hint": "staff element has to be a child of measure element."},
+ {"rule":"count(//mei:staff/@*) = 1", "renderanyway": false, "hint": "You need one attribute on staff (@n)."},
+ {"rule": "//mei:staff/@n = '1'", "renderanyway": false, "hint": "You need a @n attribute with a value of 1."},
+ {"rule": "count(//mei:layer) = 1", "renderanyway": false, "hint": "You need one layer element."},
+ {"rule": "count(//mei:layer/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the layer element."},
+ {"rule": "//mei:staff/mei:layer", "renderanyway": false, "hint": "layer element has to be a child of staff element."}
+ ]
+ },
+ {
+ "label": "First note",
+ "editorLines": 15,
+ "descFile": "102_incipit_step-04-desc.html",
+ "prefillFile": "102_incipit_step-04-prefill.xml",
+ "xmlFile": "102_incipit_step-04.xml",
+ "xpaths": [
+ {"rule": "count(//mei:note) = 1", "renderanyway": false, "hint": "You need one note element."},
+ {"rule": "count(//mei:note/@*) = 3", "renderanyway": false, "hint": "You need three attributes on note (@pname, @oct a& @dur)."},
+ {"rule": "//mei:note/@pname = 'b'", "renderanyway": false, "hint": "You need a @pname attribute with a value of b."},
+ {"rule": "//mei:note/@oct = '3'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 3."},
+ {"rule": "//mei:note/@dur = '4'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 4."}
+ ]
+ },
+ {
+ "label": "Second note",
+ "editorLines": 18,
+ "descFile": "102_incipit_step-05-desc.html",
+ "prefillFile": "102_incipit_step-05-prefill.xml",
+ "xmlFile": "102_incipit_step-05.xml",
+ "xpaths": [
+ {"rule": "count(//mei:section) = 1", "renderanyway": false, "hint": "You need one section element."},
+ {"rule": "count(//mei:section/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the section element."},
+ {"rule": "count(//mei:measure) = 2", "renderanyway": false, "hint": "You need a total of two measure elements."},
+ {"rule": "//mei:section/mei:measure", "renderanyway": false, "hint": "measure element has to be a child of section element."},
+ {"rule": "count(//mei:section/mei:measure) = 2", "renderanyway": false, "hint": "You need two measure children in section element."},
+ {"rule": "count(//mei:measure[1]/@*) = 1 and //mei:measure[1]/@n = 0", "renderanyway": false, "hint": "You need one @n attribute with a value of 0 on the first measure element (@n=0)."},
+ {"rule": "count(//mei:measure[2]/@*) = 1 and //mei:measure[2]/@n = 1", "renderanyway": false, "hint": "You need one @n attribute with a value of 1 on the second measure element (@n=1)."},
+ {"rule": "//mei:measure[1]/mei:staff", "renderanyway": false, "hint": "You need a staff in the first measure element."},
+ {"rule": "//mei:measure[2]/mei:staff", "renderanyway": false, "hint": "You need a staff in the second measure element."},
+ {"rule": "count(//mei:measure/mei:staff) = 2", "renderanyway": false, "hint": "You need a staff child in every measure element."},
+ {"rule": "count(//mei:measure[1]/mei:staff/@*) = 1", "renderanyway": false, "hint": "You need one attribute on the staff of the first measure element (@n)."},
+ {"rule": "count(//mei:measure[2]/mei:staff/@*) = 1", "renderanyway": false, "hint": "You need one attribute on the staff of the second measure element (@n)."},
+ {"rule": "//mei:measure[1]/mei:staff/@n = 1", "renderanyway": false, "hint": "You need a @n attribute with a value of 1 on the first staff element."},
+ {"rule": "//mei:measure[2]/mei:staff/@n = 1", "renderanyway": false, "hint": "You need a @n attribute with a value of 1 on the second staff element."},
+ {"rule": "//mei:measure[1]/mei:staff/mei:layer", "renderanyway": false, "hint": "You need a layer element in the first staff element."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer", "renderanyway": false, "hint": "You need a layer element in the second staff element."},
+ {"rule": "count(//mei:staff/mei:layer) = 2", "renderanyway": false, "hint": "You need a layer child in every staff element."},
+ {"rule": "count(//mei:layer/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the layer elements."},
+ {"rule": "//mei:measure[1]/mei:staff/mei:layer/mei:note", "renderanyway": false, "hint": "You need a note in the first layer element."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note", "renderanyway": false, "hint": "You need a note in the second layer element."},
+ {"rule": "count(//mei:layer/mei:note) = 2", "renderanyway": false, "hint": "You need a note child in every layer element."},
+ {"rule": "count(//mei:measure[1]/mei:staff/mei:layer/mei:note/@*) = 3", "renderanyway": false, "hint": "You need three attributes on the first note (@pname, @oct & @dur)."},
+ {"rule": "count(//mei:measure[2]/mei:staff/mei:layer/mei:note/@*) = 3", "renderanyway": false, "hint": "You need three attributes on the second note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[1]/mei:staff/mei:layer/mei:note/@pname = 'b'", "renderanyway": false, "hint": "You need a @pname attribute with a value of b on first note."},
+ {"rule": "//mei:measure[1]/mei:staff/mei:layer/mei:note/@oct = '3'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 3 on first note."},
+ {"rule": "//mei:measure[1]/mei:staff/mei:layer/mei:note/@dur = '4'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 4 on first note."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note/@pname = 'e'", "renderanyway": false, "hint": "You need a @pname attribute with a value of e on second note."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note/@oct = '4'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 4 on second note."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note/@dur = '4'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 4 on second note."}
+ ]
+ },
+ {
+ "label": "Beams",
+ "editorLines": 12,
+ "descFile": "102_incipit_step-06-desc.html",
+ "prefillFile": "102_incipit_step-06-prefill.xml",
+ "xmlFile": "102_incipit_step-06.xml",
+ "xpaths": [
+ {"rule": "count(//mei:measure) = 2", "renderanyway": false, "hint": "You need a measure element."},
+ {"rule": "count(//mei:measure[2]/@*) = 1", "renderanyway": false, "hint": "You need one attribute on measure (@n)."},
+ {"rule": "//mei:measure[2]/@n = 1", "renderanyway": false, "hint": "You need a @n attribute with a value of 1 on measure."},
+ {"rule": "//mei:measure[2]/mei:staff", "renderanyway": false, "hint": "You need a staff in the measure element."},
+ {"rule": "count(//mei:measure[2]/mei:staff/@*) = 1", "renderanyway": false, "hint": "You need one attribute on staff (@n)."},
+ {"rule": "//mei:measure[2]/mei:staff/@n = 1", "renderanyway": false, "hint": "You need a @n attribute with a value of 1 on staff."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer", "renderanyway": false, "hint": "You need a layer element in the staff element."},
+ {"rule": "count(//mei:layer/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the layer element."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[1]", "renderanyway": false, "hint": "First note element has to be a child of the layer element."},
+ {"rule": "count(//mei:measure[2]/mei:staff/mei:layer/mei:note[1]/@*) = 3", "renderanyway": false, "hint": "You need three attributes on the first note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[1]/@pname = 'e'", "renderanyway": false, "hint": "You need a @pname attribute with a value of e on first note element."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[1]/@oct = '4'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 4 on first note."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[1]/@dur = '4'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 4 on first note."},
+ {"rule": "count(//mei:beam) = '1'", "renderanyway": false, "hint": "You need one beam element."},
+ {"rule": "//mei:layer/mei:beam", "renderanyway": false, "hint": "beam element has to be a child of the layer element."},
+ {"rule": "//mei:layer/mei:note/following-sibling::mei:beam", "renderanyway": false, "hint": "beam element has to follow the first (e flat) note element."},
+ {"rule": "count(//mei:layer/mei:note/following-sibling::*) = 1", "renderanyway": false, "hint": "You need only one element to follow the first (e flat) note element."},
+ {"rule": "count(//mei:beam/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the beam element."},
+ {"rule": "count(//mei:beam/mei:note) = 2", "renderanyway": false, "hint": "You need two note elements inside the beam element."},
+ {"rule": "count(//mei:beam/mei:note[1]/@*) = 3", "renderanyway": false, "hint": "You need three attributes on the first beamed note (@pname, @oct & @dur)."},
+ {"rule": "//mei:beam/mei:note[1]/@pname = 'e'", "renderanyway": false, "hint": "You need a @pname attribute with a value of e on the first beamed note."},
+ {"rule": "//mei:beam/mei:note[1]/@oct = '4'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 4 on the first beamed note."},
+ {"rule": "//mei:beam/mei:note[1]/@dur = '8'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 8 on the first beamed note."},
+ {"rule": "count(//mei:beam/mei:note[2]/@*) = 3", "renderanyway": false, "hint": "You need three attributes on the second beamed note (@pname, @oct & @dur)."},
+ {"rule": "//mei:beam/mei:note[2]/@pname = 'g'", "renderanyway": false, "hint": "You need a @pname attribute with a value of g on the second beamed note."},
+ {"rule": "//mei:beam/mei:note[2]/@oct = '4'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 4 on the second beamed note."},
+ {"rule": "//mei:beam/mei:note[2]/@dur = '8'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 8 on the second beamed note."}
+ ]
+ },
+ {
+ "label": "Dotted rhythm",
+ "editorLines": 14,
+ "descFile": "102_incipit_step-07-desc.html",
+ "prefillFile": "102_incipit_step-07-prefill.xml",
+ "xmlFile": "102_incipit_step-07.xml",
+ "xpaths": [
+ {"rule": "count(//mei:measure) = 2", "renderanyway": false, "hint": "You need a measure element."},
+ {"rule": "count(//mei:measure[2]/@*) = 1", "renderanyway": false, "hint": "You need one attribute on the measure (@n)."},
+ {"rule": "//mei:measure[2]/@n = 1", "renderanyway": false, "hint": "You need a @n attribute with a value of 1 on measure."},
+ {"rule": "//mei:measure[2]/mei:staff", "renderanyway": false, "hint": "You need a staff in the measure element."},
+ {"rule": "count(//mei:measure[2]/mei:staff/@*) = 1", "renderanyway": false, "hint": "You need one attribute on staff (@n)."},
+ {"rule": "//mei:measure[2]/mei:staff/@n = 1", "renderanyway": false, "hint": "You need a @n attribute with a value of 1 on staff."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer", "renderanyway": false, "hint": "You need a layer element in the staff element."},
+ {"rule": "count(//mei:layer/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the layer element."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[1]", "renderanyway": false, "hint": "First note element has to be a child of layer element."},
+ {"rule": "count(//mei:measure[2]/mei:staff/mei:layer/mei:note[1]/@*) = 3", "renderanyway": false, "hint": "You need three attributes on the first note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[1]/@pname = 'e'", "renderanyway": false, "hint": "You need a @pname attribute with a value of e on first note element."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[1]/@oct = '4'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 4 on first note."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[1]/@dur = '4'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 4 on first note."},
+ {"rule": "count(//mei:beam) = '1'", "renderanyway": false, "hint": "You need one beam element."},
+ {"rule": "//mei:layer/mei:beam", "renderanyway": false, "hint": "beam element has to be a child of the layer element."},
+ {"rule": "//mei:layer/mei:note/following-sibling::mei:beam", "renderanyway": false, "hint": "beam element has to follow the first (e flat) note element."},
+ {"rule": "count(//mei:beam/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the beam element."},
+ {"rule": "count(//mei:beam/mei:note) = 2", "renderanyway": false, "hint": "You need two note elements inside the beam element."},
+ {"rule": "count(//mei:beam/mei:note[1]/@*) = 3", "renderanyway": false, "hint": "You need three attributes on the first beamed note (@pname, @oct & @dur)."},
+ {"rule": "//mei:beam/mei:note[1]/@pname = 'e'", "renderanyway": false, "hint": "You need a @pname attribute with a value of e on the first beamed note."},
+ {"rule": "//mei:beam/mei:note[1]/@oct = '4'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 4 on the first beamed note."},
+ {"rule": "//mei:beam/mei:note[1]/@dur = '8'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 8 on the first beamed note."},
+ {"rule": "count(//mei:beam/mei:note[2]/@*) = 3", "renderanyway": false, "hint": "You need three attributes on the second beamed note (@pname, @oct & @dur)."},
+ {"rule": "//mei:beam/mei:note[2]/@pname = 'g'", "renderanyway": false, "hint": "You need a @pname attribute with a value of g on second beamed note."},
+ {"rule": "//mei:beam/mei:note[2]/@oct = '4'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 4 on second beamed note."},
+ {"rule": "//mei:beam/mei:note[2]/@dur = '8'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 8 on second beamed note."},
+ {"rule": "//mei:layer/mei:beam/following-sibling::mei:note", "renderanyway": false, "hint": "One note element has to follow the beam element."},
+ {"rule": "//mei:layer/mei:beam/following-sibling::mei:note/following-sibling::mei:note", "renderanyway": false, "hint": "Another note element has to follow the note after the beam element."},
+ {"rule": "count(//mei:measure[2]/mei:staff/mei:layer/mei:note) = 3", "renderanyway": false, "hint": "You need a total of three note elements as direct childs of this measure's layer."},
+ {"rule": "count(//mei:layer/mei:note/following-sibling::*) = 3", "renderanyway": false, "hint": "You need three elements to follow the first note element."},
+ {"rule": "count(//mei:measure[2]/mei:staff/mei:layer/mei:note[2]/@*) = 4", "renderanyway": false, "hint": "You need four attributes on the dotted quarter note (@pname, @oct, @dur & @dots)."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[2]/@pname = 'f'", "renderanyway": false, "hint": "You need a @pname attribute with a value of f on the dotted quarter note."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[2]/@oct = '4'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 4 on the dotted quarter note."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[2]/@dur = '4'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 4 on the dotted quarter note."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[2]/@dots = '1'", "renderanyway": false, "hint": "You need a @dots attribute with a value of 1 on the dotted quarter note."},
+ {"rule": "count(//mei:measure[2]/mei:staff/mei:layer/mei:note[3]/@*) = 3", "renderanyway": false, "hint": "You need three attributes on the eighth note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[3]/@pname = 'd'", "renderanyway": false, "hint": "You need a @pname attribute with a value of d on the eighth note."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[3]/@oct = '4'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 4 on the eighth note."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[3]/@dur = '8'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 8 on the eighth note."}
+ ]
+ },
+ {
+ "label": "A full measure",
+ "editorLines": 14,
+ "descFile": "102_incipit_step-08-desc.html",
+ "prefillFile": "102_incipit_step-08-prefill.xml",
+ "xmlFile": "102_incipit_step-08.xml",
+ "xpaths": [
+ {"rule": "count(//mei:measure) = 3", "renderanyway": false, "hint": "You need one measure element."},
+ {"rule": "count(//mei:measure[3]/@*) = 1", "renderanyway": false, "hint": "You need one attribute on measure (@n)."},
+ {"rule": "//mei:measure[3]/@n = 2", "renderanyway": false, "hint": "You need a @n attribute with a value of 2 on measure."},
+ {"rule": "//mei:measure[3]/mei:staff", "renderanyway": false, "hint": "You need a staff element in the measure element."},
+ {"rule": "count(//mei:measure[3]/mei:staff/@*) = 1", "renderanyway": false, "hint": "You need one attribute on staff (@n)."},
+ {"rule": "//mei:measure[3]/mei:staff/@n = 1", "renderanyway": false, "hint": "You need a @n attribute with a value of 1 on staff."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer", "renderanyway": false, "hint": "You need a layer element in the staff element."},
+ {"rule": "count(//mei:layer/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the layer element."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:note[1]", "renderanyway": false, "hint": "First note element has to be child of the layer element."},
+ {"rule": "count(//mei:measure[3]/mei:staff/mei:layer/mei:note[1]/@*) = 3", "renderanyway": false, "hint": "You need three attributes on the first note element (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:note[1]/@pname = 'e'", "renderanyway": false, "hint": "You need a @pname attribute with a value of e on the first note element."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:note[1]/@oct = '4'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 4 on the first note element."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:note[1]/@dur = '4'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 4 on the first note element."},
+ {"rule": "count(//mei:measure[3]/mei:staff/mei:layer/mei:beam) = '1'", "renderanyway": false, "hint": "You need one beam element."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:beam", "renderanyway": false, "hint": "beam element has to be a child of the layer element."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:note/following-sibling::mei:beam", "renderanyway": false, "hint": "beam element has to follow the first note element."},
+ {"rule": "count(//mei:beam/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the beam element."},
+ {"rule": "count(//mei:measure[3]/mei:staff/mei:layer/mei:beam/mei:note) = 2", "renderanyway": false, "hint": "You need two note elements inside the beam element."},
+ {"rule": "count(//mei:measure[3]/mei:staff/mei:layer/mei:beam/mei:note[1]/@*) = 3", "renderanyway": false, "hint": "You need three attributes on the first beamed note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:beam/mei:note[1]/@pname = 'e'", "renderanyway": false, "hint": "You need a @pname attribute with a value of e on the first beamed note."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:beam/mei:note[1]/@oct = '4'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 4 on the first beamed note."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:beam/mei:note[1]/@dur = '8'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 8 on the first beamed note."},
+ {"rule": "count(//mei:measure[3]/mei:staff/mei:layer/mei:beam/mei:note[2]/@*) = 3", "renderanyway": false, "hint": "You need three attributes on the second beamed note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:beam/mei:note[2]/@pname = 'g'", "renderanyway": false, "hint": "You need a @pname attribute with a value of g on the second beamed note."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:beam/mei:note[2]/@oct = '4'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 4 on the second beamed note."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:beam/mei:note[2]/@dur = '8'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 8 on the second beamed note."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:beam/following-sibling::mei:note", "renderanyway": false, "hint": "One note element has to follow the beam element."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:beam/following-sibling::mei:note/following-sibling::mei:note", "renderanyway": false, "hint": "Another note element has to follow the note after the beam element."},
+ {"rule": "count(//mei:measure[3]/mei:staff/mei:layer/mei:note) = 3", "renderanyway": false, "hint": "You need a total of three note elements as childs of this measure's layer."},
+ {"rule": "count(//mei:measure[3]/mei:staff/mei:layer/mei:note/following-sibling::*) = 3", "renderanyway": false, "hint": "You need three elements to follow the first note element."},
+ {"rule": "count(//mei:measure[3]/mei:staff/mei:layer/mei:note[2]/@*) = 4", "renderanyway": false, "hint": "You need four attributes on the dotted quarter note (@pname, @oct, @dur & @dots)."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:note[2]/@pname = 'b'", "renderanyway": false, "hint": "You need a @pname attribute with a value of b on the dotted quarter note."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:note[2]/@oct = '4'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 4 on the dotted quarter note."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:note[2]/@dur = '4'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 4 on the dotted quarter note."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:note[2]/@dots = '1'", "renderanyway": false, "hint": "You need a @dots attribute with a value of 1 on the dotted quarter note."},
+ {"rule": "count(//mei:measure[3]/mei:staff/mei:layer/mei:note[3]/@*) = 3", "renderanyway": false, "hint": "You need three attributes on the eighth note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:note[3]/@pname = 'g'", "renderanyway": false, "hint": "You need a @pname attribute with a value of g on the eighth note ."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:note[3]/@oct = '4'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 4 on the eighth note ."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:note[3]/@dur = '8'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 8 on the eighth note ."}
+ ]
+ },
+ {
+ "label": "Final two measures",
+ "editorLines": 14,
+ "descFile": "102_incipit_step-09-desc.html",
+ "prefillFile": "102_incipit_step-09-prefill.xml",
+ "xmlFile": "102_incipit_step-09.xml",
+ "xpaths": [
+ {"rule": "count(//mei:measure) = 5", "renderanyway": false, "hint": "You need two measure elements."},
+ {"rule": "//mei:measure[4]/following-sibling::mei:measure", "renderanyway": false, "hint": "Measures have to follow each other."},
+ {"rule": "count(//mei:measure[4]/@*) = 1", "renderanyway": false, "hint": "You need one attribute on the first measure element (@n)."},
+ {"rule": "//mei:measure[4]/@n = 3", "renderanyway": false, "hint": "You need a @n attribute with a value of 3 on the first measure element."},
+ {"rule": "count(//mei:measure[5]/@*) = 1", "renderanyway": false, "hint": "You need one attribute on the second measure element (@n)."},
+ {"rule": "//mei:measure[5]/@n = 4", "renderanyway": false, "hint": "You need a @n attribute with a value of 4 on the second measure element."},
+ {"rule": "//mei:measure[4]/mei:staff", "renderanyway": false, "hint": "Measure n=3: You need a staff element inside the measure element."},
+ {"rule": "count(//mei:measure[4]/mei:staff/@*) = 1", "renderanyway": false, "hint": "Measure n=3: You need one attribute on staff (@n)."},
+ {"rule": "//mei:measure[4]/mei:staff/@n = 1", "renderanyway": false, "hint": "Measure n=3: You need a @n attribute with a value of 1 on staff."},
+ {"rule": "//mei:measure[5]/mei:staff", "renderanyway": false, "hint": "Measure n=4: You need a staff element inside the measure element."},
+ {"rule": "count(//mei:measure[5]/mei:staff/@*) = 1", "renderanyway": false, "hint": "Measure n=4: You need one attribute on staff (@n)."},
+ {"rule": "//mei:measure[5]/mei:staff/@n = 1", "renderanyway": false, "hint": "Measure n=4: You need a @n attribute with a value of 1 on staff."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer", "renderanyway": false, "hint": "Measure n=3: You need a layer element inside staff."},
+ {"rule": "count(//mei:layer/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the layer elements."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer", "renderanyway": false, "hint": "Measure n=4: You need a layer element inside staff."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam) = '2'", "renderanyway": false, "hint": "Measure n=3: You need two beam elements as direct children of layer."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:note) = '1'", "renderanyway": false, "hint": "Measure n=3: You need one note element as direct child of layer."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/following-sibling::mei:note/following-sibling::mei:beam", "renderanyway": false, "hint": "Measure n=3: Note element has to be placed between the two beam elements."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/*) = '3'", "renderanyway": false, "hint": "Measure n=3: You need a total of 3 elements as children of layer."},
+ {"rule": "count(//mei:beam/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the beam elements."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:note/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the note element (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:note/@pname = 'e'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of e on note element."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:note/@oct = '5'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 5 on note element."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:note/@dur = '4'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 4 on note element."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note) = 4", "renderanyway": false, "hint": "Measure n=3: You need four note elements inside the first beam element."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[1]/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the first beamed note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[1]/@pname = 'a'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of a on the first beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[1]/@oct = '4'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 4 on the first beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[1]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the first beamed note."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[2]/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the second beamed note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[2]/@pname = 'b'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of b on the second beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[2]/@oct = '4'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 4 on the second beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[2]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the second beamed note."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[3]/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the third beamed note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[3]/@pname = 'c'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of c on the third beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[3]/@oct = '5'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 5 on the third beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[3]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the third beamed note."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[4]/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the fourth beamed note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[4]/@pname = 'd'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of d on the fourth beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[4]/@oct = '5'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 5 on the fourth beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[4]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the fourth beamed note."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note) = 2", "renderanyway": false, "hint": "Measure n=3: You need two note elements inside the second beam element."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[1]/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the first beamed note (@pname, @oct & @dur) of the second beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[1]/@pname = 'd'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of d on the first beamed note of the second beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[1]/@oct = '5'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 5 on the first beamed note of the second beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[1]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the first beamed note of the second beam."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[2]/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the second beamed note (@pname, @oct & @dur) of the second beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[2]/@pname = 'b'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of b on the second beamed note of the second beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[2]/@oct = '4'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 4 on the second beamed note of the second beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[2]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the second beamed note of the second beam."},
+ {"rule": "count(//mei:measure[5]/mei:staff/mei:layer/mei:note) = '2'", "renderanyway": false, "hint": "Measure n=4: You need two note elements as children of layer."},
+ {"rule": "count(//mei:measure[5]/mei:staff/mei:layer/mei:rest) = '1'", "renderanyway": false, "hint": "Measure n=4: You need one rest element as child of layer."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer/mei:note[1]/following-sibling::mei:note/following-sibling::mei:rest", "renderanyway": false, "hint": "Measure n=4: Rest element has to follow the two note elements."},
+ {"rule": "count(//mei:measure[5]/mei:staff/mei:layer/*) = '3'", "renderanyway": false, "hint": "Measure n=4: You need a total of 3 elements as children of layer."},
+ {"rule": "count(//mei:measure[5]/mei:staff/mei:layer/mei:note[1]/@*) = 3", "renderanyway": false, "hint": "Measure n=4: You need three attributes on the first note element (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer/mei:note[1]/@pname = 'c'", "renderanyway": false, "hint": "Measure n=4: You need a @pname attribute with a value of c on the first note element."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer/mei:note[1]/@oct = '5'", "renderanyway": false, "hint": "Measure n=4: You need an @oct attribute with a value of 5 on the first note element."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer/mei:note[1]/@dur = '4'", "renderanyway": false, "hint": "Measure n=4: You need a @dur attribute with a value of 4 on the first note element."},
+ {"rule": "count(//mei:measure[5]/mei:staff/mei:layer/mei:note[2]/@*) = 3", "renderanyway": false, "hint": "Measure n=4: You need three attributes on the second note element (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer/mei:note[2]/@pname = 'b'", "renderanyway": false, "hint": "Measure n=4: You need a @pname attribute with a value of b on the second note element."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer/mei:note[2]/@oct = '4'", "renderanyway": false, "hint": "Measure n=4: You need an @oct attribute with a value of 4 on the second note element."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer/mei:note[2]/@dur = '4'", "renderanyway": false, "hint": "Measure n=4: You need a @dur attribute with a value of 4 on the second note element."},
+ {"rule": "count(//mei:measure[5]/mei:staff/mei:layer/mei:rest/@*) = 1", "renderanyway": false, "hint": "Measure n=4: You need one attribute on the rest element (@dur)."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer/mei:rest/@dur = '4'", "renderanyway": false, "hint": "Measure n=4: You need a @dur attribute with a value of 4 on the rest element."}
+ ]
+ },
+ {
+ "label": "Articulations",
+ "editorLines": 50,
+ "descFile": "102_incipit_step-10-desc.html",
+ "prefillFile": "102_incipit_step-10-prefill.xml",
+ "xmlFile": "102_incipit_step-10.xml",
+ "xpaths": [
+ {"rule": "count(//mei:measure) = 5", "renderanyway": false, "hint": "You need three measure elements."},
+ {"rule": "//mei:measure[4]/following-sibling::mei:measure", "renderanyway": false, "hint": "Measures have to follow each other."},
+ {"rule": "count(//mei:measure[4]/@*) = 1", "renderanyway": false, "hint": "You need one attribute on the first measure element (@n)."},
+ {"rule": "//mei:measure[4]/@n = 3", "renderanyway": false, "hint": "You need a @n attribute with a value of 3 on the first measure element."},
+ {"rule": "count(//mei:measure[5]/@*) = 1", "renderanyway": false, "hint": "You need one attribute on the second measure element (@n)."},
+ {"rule": "//mei:measure[5]/@n = 4", "renderanyway": false, "hint": "You need a @n attribute with a value of 4 on the second measure element."},
+ {"rule": "//mei:measure[4]/mei:staff", "renderanyway": false, "hint": "You need a staff element inside the first measure element."},
+ {"rule": "count(//mei:measure[4]/mei:staff/@*) = 1", "renderanyway": false, "hint": "You need one attribute on staff (@n)."},
+ {"rule": "//mei:measure[4]/mei:staff/@n = 1", "renderanyway": false, "hint": "You need a @n attribute with a value of 1 on staff."},
+ {"rule": "//mei:measure[5]/mei:staff", "renderanyway": false, "hint": "You need a staff element inside the second measure element."},
+ {"rule": "count(//mei:measure[5]/mei:staff/@*) = 1", "renderanyway": false, "hint": "You need one attribute on staff (@n)."},
+ {"rule": "//mei:measure[5]/mei:staff/@n = 1", "renderanyway": false, "hint": "You need a @n attribute with a value of 1 on staff."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer", "renderanyway": false, "hint": "Measure n=3: You need a layer element inside staff."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer", "renderanyway": false, "hint": "Measure n=4: You need a layer element inside staff."},
+ {"rule": "count(//mei:layer/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the layer elements."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam) = '2'", "renderanyway": false, "hint": "Measure n=3: You need two beam elements as children of layer."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:note) = '1'", "renderanyway": false, "hint": "Measure n=3: You need one note element as child of layer."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/following-sibling::mei:note/following-sibling::mei:beam", "renderanyway": false, "hint": "Measure n=3: Note element has to be placed between the two beam elements."},
+ {"rule": "count(//mei:beam/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the beam elements."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:note/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the note element (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:note/@pname = 'e'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of e on the note element."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:note/@oct = '5'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 5 on the note element."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:note/@dur = '4'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 4 on the note element."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note) = 4", "renderanyway": false, "hint": "Measure n=3: You need four note elements inside the first beam element."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[1]/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the first beamed note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[1]/@pname = 'a'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of a on the first beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[1]/@oct = '4'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 4 on the first beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[1]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the first beamed note."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[2]/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the second beamed note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[2]/@pname = 'b'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of b on the second beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[2]/@oct = '4'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 4 on the second beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[2]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the second beamed note."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[3]/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the third beamed note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[3]/@pname = 'c'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of c on the third beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[3]/@oct = '5'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 5 on the third beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[3]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the third beamed note."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[4]/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the fourth beamed note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[4]/@pname = 'd'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of d on the fourth beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[4]/@oct = '5'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 5 on the fourth beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[4]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the fourth beamed note."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note) = 2", "renderanyway": false, "hint": "Measure n=3: You need two note elements inside the second beam element."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[1]/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the first beamed note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[1]/@pname = 'd'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of d on the first beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[1]/@oct = '5'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 5 on the first beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[1]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the first beamed note."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[2]/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the second beamed note (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[2]/@pname = 'b'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of b on the second beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[2]/@oct = '4'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 4 on the second beamed note."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[2]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the second beamed note."},
+ {"rule": "count(//mei:measure[5]/mei:staff/mei:layer/mei:note) = '2'", "renderanyway": false, "hint": "Measure n=4: You need two note elements as children of layer."},
+ {"rule": "count(//mei:measure[5]/mei:staff/mei:layer/mei:rest) = '1'", "renderanyway": false, "hint": "Measure n=4: You need one rest element as child of layer."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer/mei:note[1]/following-sibling::mei:note/following-sibling::mei:rest", "renderanyway": false, "hint": "Measure n=4: Rest element has to follow the two note elements."},
+ {"rule": "count(//mei:measure[5]/mei:staff/mei:layer/mei:note[1]/@*) = 3", "renderanyway": false, "hint": "Measure n=4: You need three attributes on the first note element (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer/mei:note[1]/@pname = 'c'", "renderanyway": false, "hint": "Measure n=4: You need a @pname attribute with a value of c on the first note element."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer/mei:note[1]/@oct = '5'", "renderanyway": false, "hint": "Measure n=4: You need an @oct attribute with a value of 5 on the first note element."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer/mei:note[1]/@dur = '4'", "renderanyway": false, "hint": "Measure n=4: You need a @dur attribute with a value of 4 on the first note element."},
+ {"rule": "count(//mei:measure[5]/mei:staff/mei:layer/mei:note[2]/@*) = 3", "renderanyway": false, "hint": "Measure n=4: You need three attributes on the second note element (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer/mei:note[2]/@pname = 'b'", "renderanyway": false, "hint": "Measure n=4: You need a @pname attribute with a value of b on the second note element."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer/mei:note[2]/@oct = '4'", "renderanyway": false, "hint": "Measure n=4: You need an @oct attribute with a value of 4 on the second note element."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer/mei:note[2]/@dur = '4'", "renderanyway": false, "hint": "Measure n=4: You need a @dur attribute with a value of 4 on the second note element."},
+ {"rule": "count(//mei:measure[5]/mei:staff/mei:layer/mei:rest/@*) = 1", "renderanyway": false, "hint": "Measure n=4: You need one attribute on the rest element (@dur)."},
+ {"rule": "//mei:measure[5]/mei:staff/mei:layer/mei:rest/@dur = '4'", "renderanyway": false, "hint": "Measure n=4: You need a @dur attribute with a value of 4 on the rest element."},
+ {"rule": "count(//mei:measure[2]/mei:staff/mei:layer/mei:note[2]/mei:artic) = '1'", "renderanyway": false, "hint": "Measure n=1: You need an artic element as children of the second note element."},
+ {"rule": "count(//mei:measure[2]/mei:staff/mei:layer/mei:note[2]/mei:artic/@*) = 2", "renderanyway": false, "hint": "Measure n=1: You need two attributes on the artic element (@artic, @place)."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[2]/mei:artic/@artic = 'acc'", "renderanyway": false, "hint": "Measure n=1: You need a @artic attribute with a value of acc on artic element."},
+ {"rule": "//mei:measure[2]/mei:staff/mei:layer/mei:note[2]/mei:artic/@place = 'above'", "renderanyway": false, "hint": "Measure n=1: You need an @place attribute with a value of above on the artic element."},
+ {"rule": "count(//mei:measure[3]/mei:staff/mei:layer/mei:note[2]/mei:artic) = '1'", "renderanyway": false, "hint": "Measure n=2: You need a artic element as children of the second note element."},
+ {"rule": "count(//mei:measure[3]/mei:staff/mei:layer/mei:note[2]/mei:artic/@*) = 2", "renderanyway": false, "hint": "Measure n=2: You need two attributes on the artic element (@artic, @place)."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:note[2]/mei:artic/@artic = 'acc'", "renderanyway": false, "hint": "Measure n=2: You need a @artic attribute with a value of acc on artic element."},
+ {"rule": "//mei:measure[3]/mei:staff/mei:layer/mei:note[2]/mei:artic/@place = 'above'", "renderanyway": false, "hint": "Measure n=2: You need an @place attribute with a value of above on the artic element."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:note/mei:artic) = '1'", "renderanyway": false, "hint": "Measure n=3: You need a artic element as children of the note element."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:note/mei:artic/@*) = 2", "renderanyway": false, "hint": "Measure n=3: You need two attributes on the artic element (@artic, @place)."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:note/mei:artic/@artic = 'acc'", "renderanyway": false, "hint": "Measure n=3: You need a @artic attribute with a value of acc on artic element."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:note/mei:artic/@place = 'above'", "renderanyway": false, "hint": "Measure n=3: You need an @place attribute with a value of above on the artic element."}
+ ]
+ },
+ {
+ "label": "Dynamics (referencing tstamps)",
+ "editorLines": 10,
+ "descFile": "102_incipit_step-11-desc.html",
+ "prefillFile": "102_incipit_step-11-prefill.xml",
+ "xmlFile": "102_incipit_step-11.xml",
+ "xpaths": [
+ {"rule": "count(//mei:measure[@n=0]) = 1", "renderanyway": false, "hint": "You need one measure with n = 0."},
+ {"rule": "//mei:measure[1]/mei:staff", "renderanyway": false, "hint": "You need a staff element inside the measure element."},
+ {"rule": "count(//mei:measure[1]/mei:staff/@*) = 1", "renderanyway": false, "hint": "You need one attribute on staff (@n)."},
+ {"rule": "//mei:measure[1]/mei:staff/@n = 1", "renderanyway": false, "hint": "You need a @n attribute with a value of 1 on staff."},
+ {"rule": "//mei:measure[1]/mei:staff/mei:layer", "renderanyway": false, "hint": "You need a layer element inside staff."},
+ {"rule": "count(//mei:measure[1]/mei:staff/mei:layer/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the layer element."},
+ {"rule": "count(//mei:measure[1]/mei:staff/mei:layer/mei:note) = 1", "renderanyway": false, "hint": "You need one note element."},
+ {"rule": "//mei:measure[1]/mei:staff/mei:layer/mei:note", "renderanyway": false, "hint": "The note element has to be a child of the layer element."},
+ {"rule": "count(//mei:measure[1]/mei:staff/mei:layer/mei:note/@*) = 3", "renderanyway": false, "hint": "You need three attributes on the note element (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[1]/mei:staff/mei:layer/mei:note/@pname = 'b'", "renderanyway": false, "hint": "You need a @pname attribute with a value of b on note."},
+ {"rule": "//mei:measure[1]/mei:staff/mei:layer/mei:note/@oct = '3'", "renderanyway": false, "hint": "You need an @oct attribute with a value of 3 on note."},
+ {"rule": "//mei:measure[1]/mei:staff/mei:layer/mei:note/@dur = '4'", "renderanyway": false, "hint": "You need a @dur attribute with a value of 4 on note."},
+ {"rule": "count(//mei:measure[1]/mei:dynam) = '1'", "renderanyway": false, "hint": "You need a dynam element as children of measure."},
+ {"rule": "//mei:measure[1]/mei:staff/following-sibling::mei:dynam", "renderanyway": false, "hint": "dynam element as has to follow the staff element."},
+ {"rule": "count(//mei:measure[1]/mei:dynam/@*) = 3", "renderanyway": false, "hint": "You need three attributes on the dynam element (@staff, @tstamp & @place)."},
+ {"rule": "//mei:measure[1]/mei:dynam/@staff = '1'", "renderanyway": false, "hint": "You need a @staff attribute with a value of 1 on the dynam element."},
+ {"rule": "//mei:measure[1]/mei:dynam/@tstamp = '1'", "renderanyway": false, "hint": "You need a @tstamp attribute with a value of 1 on the dynam element."},
+ {"rule": "//mei:measure[1]/mei:dynam/@place = 'below'", "renderanyway": false, "hint": "You need an @place attribute with a value of below on the dynam element."},
+ {"rule": "//mei:measure[1]/mei:dynam/text() = 'ff'", "renderanyway": false, "hint": "You need a text value of ff as content of the dynam element."}
+ ]
+ },
+ {
+ "label": "Slurs (referencing xml:id)",
+ "editorLines": 25,
+ "descFile": "102_incipit_step-12-desc.html",
+ "prefillFile": "102_incipit_step-12-prefill.xml",
+ "xmlFile": "102_incipit_step-12.xml",
+ "xpaths": [
+ {"rule": "count(//mei:measure[@n=3]) = 1", "renderanyway": false, "hint": "You need one measure with n = 3."},
+ {"rule": "//mei:measure[4]/mei:staff", "renderanyway": false, "hint": "You need a staff element inside the measure element."},
+ {"rule": "count(//mei:measure[4]/mei:staff/@*) = 1", "renderanyway": false, "hint": "You need one attribute on staff (@n)."},
+ {"rule": "//mei:measure[4]/mei:staff/@n = 1", "renderanyway": false, "hint": "You need a @n attribute with a value of 1 on staff."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer", "renderanyway": false, "hint": "You need a layer element inside staff."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the layer element."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam) = '2'", "renderanyway": false, "hint": "Measure n=3: You need two beam elements as children of layer."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:note) = '1'", "renderanyway": false, "hint": "Measure n=3: You need one note element as child of layer."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/following-sibling::mei:note/following-sibling::mei:beam", "renderanyway": false, "hint": "Measure n=3: Note element has to be placed between the two beam elements."},
+ {"rule": "count(//mei:beam/@*) = 0", "renderanyway": false, "hint": "You do not need an attribute on the beam elements."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:note/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the note element (@pname, @oct & @dur)."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:note/@pname = 'e'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of e on the note element."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:note/@oct = '5'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 5 on the note element."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:note/@dur = '4'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 4 on the note element."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note) = 4", "renderanyway": false, "hint": "Measure n=3: You need four note elements inside the first beam element."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[1]/@pname = 'a'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of a on the first beamed note of the first beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[1]/@oct = '4'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 4 on the first beamed note of the first beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[1]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the first beamed note of the first beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[2]/@pname = 'b'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of b on the second beamed note of the first beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[2]/@oct = '4'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 4 on the second beamed note of the first beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[2]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the second beamed note of the first beam."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[3]/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the third beamed note (@pname, @oct & @dur) of the first beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[3]/@pname = 'c'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of c on the third beamed note of the first beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[3]/@oct = '5'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 5 on the third beamed note of the first beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[3]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the third beamed note of the first beam."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[4]/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the fourth beamed note (@pname, @oct & @dur) of the first beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[4]/@pname = 'd'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of d on the fourth beamed note of the first beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[4]/@oct = '5'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 5 on the fourth beamed note of the first beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[4]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the fourth beamed note of the first beam."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note) = 2", "renderanyway": false, "hint": "Measure n=3: You need two note elements inside the second beam element."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[1]/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the first beamed note (@pname, @oct & @dur) of the second beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[1]/@pname = 'd'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of d on the first beamed note of the second beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[1]/@oct = '5'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 5 on the first beamed note of the second beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[1]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the first beamed note of the second beam."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[2]/@*) = 3", "renderanyway": false, "hint": "Measure n=3: You need three attributes on the second beamed note (@pname, @oct & @dur) of the second beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[2]/@pname = 'b'", "renderanyway": false, "hint": "Measure n=3: You need a @pname attribute with a value of b on the second beamed note of the second beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[2]/@oct = '4'", "renderanyway": false, "hint": "Measure n=3: You need an @oct attribute with a value of 4 on the second beamed note of the second beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[2]/mei:note[2]/@dur = '8'", "renderanyway": false, "hint": "Measure n=3: You need a @dur attribute with a value of 8 on the second beamed note of the second beam."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:note/mei:artic) = '1'", "renderanyway": false, "hint": "Measure n=3: You need a artic element as children of the note element."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:note/mei:artic/@*) = 2", "renderanyway": false, "hint": "Measure n=3: You need two attributes on the artic element (@artic, @place)."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:note/mei:artic/@artic = 'acc'", "renderanyway": false, "hint": "Measure n=3: You need a @artic attribute with a value of acc on artic element."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:note/mei:artic/@place = 'above'", "renderanyway": false, "hint": "Measure n=3: You need an @place attribute with a value of above on the artic element."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[1]/@*) = 4", "renderanyway": false, "hint": "You need four attributes on the first beamed note (@pname, @oct, @dur & @xml:id) of the first beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[1]/@*[name()='xml:id'] = 'd1e4614'", "renderanyway": false, "hint": "You need a @xml:id attribute with a value of `d1e4614` on the first beamed note of the first beam."},
+ {"rule": "count(//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[2]/@*) = 4", "renderanyway": false, "hint": "You need four attributes on the second beamed note (@pname, @oct, @dur & @xml:id) of the first beam."},
+ {"rule": "//mei:measure[4]/mei:staff/mei:layer/mei:beam[1]/mei:note[2]/@*[name()='xml:id'] = 'd1e4615'", "renderanyway": false, "hint": "You need a @xml:id attribute with a value of `d1e4615` on the second beamed note of the first beam."},
+ {"rule": "count(//mei:measure[4]/mei:slur) = '1'", "renderanyway": false, "hint": "You need a slur element as child of measure."},
+ {"rule": "//mei:measure[4]/mei:staff/following-sibling::mei:slur", "renderanyway": false, "hint": "slur element has to follow the staff element."},
+ {"rule": "count(//mei:measure[4]/mei:slur/@*) = 4", "renderanyway": false, "hint": "You need four attributes on the slur element (@staff, @curvedir, @startid & @endid)."},
+ {"rule": "//mei:measure[4]/mei:slur/@staff = '1'", "renderanyway": false, "hint": "You need a @staff attribute with a value of 1 on slur."},
+ {"rule": "//mei:measure[4]/mei:slur/@curvedir = 'above'", "renderanyway": false, "hint": "You need a @curvedir attribute with a value of above on slur."},
+ {"rule": "//mei:measure[4]/mei:slur/@startid = '#d1e4614'", "renderanyway": false, "hint": "You need a @startid attribute with a value of #d1e4614 on slur."},
+ {"rule": "//mei:measure[4]/mei:slur/@endid = '#d1e4615'", "renderanyway": false, "hint": "You need an @endid attribute with a value of #d1e4615 on slur."}
+ ]
+ }
+ ],
+ "end": "102_incipit_end.html",
+ "resp": [
+ {
+ "name": "Margrethe S. Bue",
+ "affiliation": "National Library of Norway"
+ },
+ {
+ "name": "Sonja Wronkowska",
+ "affiliation": "RISM Poland | National Library of Poland"
+ },
+ {
+ "name": "Debra Nakos",
+ "affiliation": "University of Maryland, College Park"
+ },
+ {
+ "name": "Johannes Kepper",
+ "affiliation": "Beethovens Werkstatt | Universität Paderborn"
+ },
+ {
+ "name": "Andrew Hankinson",
+ "affiliation": "Bodleian Libraries | University of Oxford"
+ },
+ {
+ "name": "Stefan Münnich",
+ "affiliation": "Anton Webern Gesamtausgabe | University of Basel"
+ }
+ ]
+}
diff --git a/_tutorials-BA/102_incipit/102_incipit.md b/_tutorials-BA/102_incipit/102_incipit.md
new file mode 100644
index 00000000..638b91b7
--- /dev/null
+++ b/_tutorials-BA/102_incipit/102_incipit.md
@@ -0,0 +1,12 @@
+---
+layout: tutorials
+type: tutorial
+name: "ADVANCED: Incipit encoding"
+fullname: "An advanced tutorial on how to encode incipits in MEI"
+data: "102_incipit.json"
+---
+Welcome! In this tutorial you will learn how to encode an incipit (initial sequence of notes of a musical piece) in MEI, using the following example:
+
+
+
+By the way: this is the beginning of _Hallingdal Bataljons Marsch_, the Opus 1 of the Norwegian composer [Johan Halvorsen](https://en.wikipedia.org/wiki/Johan_Halvorsen) (1864–1935).
diff --git a/_tutorials-BA/102_incipit/102_incipit_end.html b/_tutorials-BA/102_incipit/102_incipit_end.html
new file mode 100644
index 00000000..b27d1300
--- /dev/null
+++ b/_tutorials-BA/102_incipit/102_incipit_end.html
@@ -0,0 +1,8 @@
+
+
Congratulations!
+
You have now successfully finished this advanced tutorial, and you should be able to encode a single melody of one voice with multiple measures, different note and rest values, beams, slurs and dynamics.
+
+
Here are some other tutorials we would like to recommend as next steps with MEI. Of course, you can always come back to these (or even this one) when you would like to remind yourself how to do certain things in MEI.
+
+
As soon as you have familiarized yourself with MEI to some degree, we invite you to share your experience with the MEI Community and write a tutorial on an aspect of MEI that you're particularly interested in. You don't have to be an expert for this – it's good to have tutorials on different levels. Often a tutorial written by other beginners which just mastered a task is easier to follow than a guide written by someone who's not seeing the problem at all. We do have a tutorial on how to write tutorials, and there are templates to follow. It's that easy to become an active member of the MEI Community :-)
+
diff --git a/_tutorials-BA/102_incipit/step-01/102_incipit_step-01-desc.html b/_tutorials-BA/102_incipit/step-01/102_incipit_step-01-desc.html
new file mode 100644
index 00000000..dede0952
--- /dev/null
+++ b/_tutorials-BA/102_incipit/step-01/102_incipit_step-01-desc.html
@@ -0,0 +1,11 @@
+
+
Step one: encoding the structural skeleton of the example.
+
+
To encode the melody line of this example, you will need to include information about how the score and the staves are organized. In MEI, that kind of information is given via the elements <scoreDef> (score definition), <staffGrp> (staff group) and <staffDef> (staff definition). Hereby, the <scoreDef> is used to specify the common parameters of a score, the <staffGrp> provides information about the grouping of staves, and <staffDef> contains all the things related to an individual staff. Altogether, these elements provide the structural context for the musical content, e.g. information about the number, grouping or order of staves, about the clef, the key signature, or the time signature.
+
+
+
+
For now let's start with a skeleton of the structure.
+
+
In the editor below, please enter a <scoreDef> element (score definition) that contains a child element <staffGrp> (staff group) and its child element <staffDef> (staff definition). For a visual output (rendition) of the encoding, more information has to be provided in the next steps.
+
diff --git a/_tutorials-BA/102_incipit/step-01/102_incipit_step-01-prefill.xml b/_tutorials-BA/102_incipit/step-01/102_incipit_step-01-prefill.xml
new file mode 100644
index 00000000..44fbfea5
--- /dev/null
+++ b/_tutorials-BA/102_incipit/step-01/102_incipit_step-01-prefill.xml
@@ -0,0 +1 @@
+
diff --git a/_tutorials-BA/102_incipit/step-02/102_incipit_step-02-desc.html b/_tutorials-BA/102_incipit/step-02/102_incipit_step-02-desc.html
new file mode 100644
index 00000000..cef43c98
--- /dev/null
+++ b/_tutorials-BA/102_incipit/step-02/102_incipit_step-02-desc.html
@@ -0,0 +1,24 @@
+
+
Step two: adding some attributes to the structural skeleton that you created in the previous step. These attributes will provide basic information about the staff,
+ clef and key of the example.
+
+
You've learned in the previous step that the <scoreDef> element is used to specify the common parameters of a score, and <staffDef> contains all the metadata related to an individual staff. Obviously, there is only one staff in this example incipit, so it would be possible to declare the key signature (3 flats) and the meter symbol (cut time) in <staffDef>. But let's move this information into <scoreDef>, assuming that the key and meter are the same for all other instruments or parts of the whole score of Halvorsen's Opus 1. To specify a certain key or meter, you need to use the following attributes of <scoreDef> and add them to the <scoreDef> element:
+
+
@key.sig (key signature) – the number of sharps/flats in written key signature, use “3f” for 3 flats.
+
@meter.sym (meter symbol) – use “cut” for cut time (C/).
+
+
+
+
+
The clef, in turn, is described in the <staffDef> element, because it is related to the individual staff (other instruments can have other clefs). You need to use the following attributes of <staffDef>:
+
+
@n (ordinal number) – the staff's position within the surrounding <staffGrp>, use ”1” for the first (and only) staff
+
@lines – use “5” for five-line staff
+
@clef.shape – the value for the clef symbol: use “G” for a G clef symbol.
+
@clef.line – the staff line on which the clef is placed (counting from the bottom), use “2”.
+
+
+
Add the attributes described above and their respective values to <scoreDef> and <staffDef> in the editor below. (For a rendition, there is still some more information needed. Let's go ahead!)
+
+
PS: Although we refer to attributes with the prepended @-sign in text, this is not necessary (or even allowed) in the encoding.
+
diff --git a/_tutorials-BA/102_incipit/step-03/102_incipit_step-03-desc.html b/_tutorials-BA/102_incipit/step-03/102_incipit_step-03-desc.html
new file mode 100644
index 00000000..3a37e4b9
--- /dev/null
+++ b/_tutorials-BA/102_incipit/step-03/102_incipit_step-03-desc.html
@@ -0,0 +1,15 @@
+
+
Step three: the setup of a single <measure> with an empty <staff> and <layer>.
+
+
Well done! You have declared the necessary metadata about the score and staff organization. On the way to the encoding of the first note of the example, you will have to prepare the "environment" for it, i.e. the measure, staff and layer (voice).
+
+
In MEI, the <section> element is the container for <measure> elements and it is positioned directly
+ after the score definition (<scoreDef>). <measure> elements can contain multiple staves (<staff>) which can have multiple layers (<layer>). The <layer> element will be
+ the parent element for the <note> elements in the next step.
+
+
To indicate the numbered position of measures, staves or layers, the attribute @n can be used.
+
+
Set up the pickup measure: In the editor, insert a <section> element. Inside <section>, add an empty <measure> element and set the number of the pickup measure to "0". Add a child element <staff> to the <measure> element and set its number to "1" (first staff in measure 0). Then add an unnumbered child element <layer> to the <staff> element.
+
+
PS: Having the necessary information provided in scoredef and section/measure, the renderer is now able to visualize the encoding. You may play a little bit with the attribute values of <scoreDef> and <staffDef> to see how they influence the rendering.
Step four: encoding of the first note of this example.
+
+
Having prepared the structure of the pick up measure in the previous step, you are now ready to encode the first note of the example. In MEI, notes describe single pitched events that are encoded in, surprise, <note> elements, whereby <note> elements are allowed to be children of <layer>. You can define the main note characteristics like pitch and duration by using the following attributes on <note>:
+
+
+
@pname (pitch name) – lower case letters from “a” to “g”, use “b” here.
+
@oct (octave) – pitch’s octave value as integers from “0”-”9”, C4 being the pitch specified by the C clef, use “3”
+
@dur (duration) – e.g. “1” for whole note, “2” for half note, “4” for quarter note, “8” for eighth note, “16” for sixteenth note, … “2048” for 2048th note, use “4”
+
+
+
Here is an example of how to encode a whole note C4: <note pname="c" oct="4" dur="1"></note>.
+
+
In the editor below, please enter the encoding of the first note of the example inside the <layer> element.
+
+
PS: If you are interested in a tutorial only on <note>s, see our Quickstart tutorial.
Step five: combining what you've learned in the last two steps, encoding at once the structure of the next measure and the second note of the example.
+
+
In the editor below, add another <measure> element (@n="1") with staff (also @n="1") and with layer next to the existing pickup measure. Add the second note of the example (a quarter note e flat 4) to this new measure. Don’t worry about the measure's content being too short in the given time signature – you’ll fill it in in the next steps.
+
+
PS: The encoding will be rendered as soon as you will have entered the new note.
Great! You have encoded the first note of the first full measure. The next two notes of the example are grouped under a beam. To express this in MEI, the <beam> element is to be used. <beam> is a container for a series of explicitly beamed events (like notes, rests or chords) that begins and ends entirely within the same measure.
+
+
In the editor below, please add a <beam> element at the specified position before adding the two child <note>s separately (e flat and g). Do remember to include the corresponding attribute values on the <note> elements.
The next two notes in the example introduce a new rhythmic figure, including a dotted quarter and an eighth note. To encode a dotted rhythm, you need to use the @dots attribute on a <note> element and set the number of dots as the attribute's value, e.g. “1” for one dot or “2” for two dots.
+
+
Please encode the rest of the measure (@n=1) in the editor below by adding two <note> elements with different rhythmic values (dotted quarter, eighth) next to the <beam> element that you have added in the previous step.
Step eight: encoding the complete next measure to repeat all the things learned in the previous steps.
+
+
Please encode the next measure (@n=2) in the editor below. Add a <measure> and <staff> element and a <layer> element which contains four child elements: a quarter <note> (e flat 4), a <beam> with two eighth <note>s (e flat 4, g4) and a dotted quarter <note> (b flat 4) with an eighth <note> (g4).
+
+
As an additional challenge, the editor box provides no prefilled content this time, so you do not get any orientation from the encoding of the previous measures. In any case of uncertainty, consider the hints below the editor box that should guide you through this task.
+
diff --git a/_tutorials-BA/102_incipit/step-08/102_incipit_step-08-prefill.xml b/_tutorials-BA/102_incipit/step-08/102_incipit_step-08-prefill.xml
new file mode 100644
index 00000000..44fbfea5
--- /dev/null
+++ b/_tutorials-BA/102_incipit/step-08/102_incipit_step-08-prefill.xml
@@ -0,0 +1 @@
+
diff --git a/_tutorials-BA/102_incipit/step-09/102_incipit_step-09-desc.html b/_tutorials-BA/102_incipit/step-09/102_incipit_step-09-desc.html
new file mode 100644
index 00000000..97070241
--- /dev/null
+++ b/_tutorials-BA/102_incipit/step-09/102_incipit_step-09-desc.html
@@ -0,0 +1,11 @@
+
+
Step nine: Encoding the note values of the final two measures of the example.
+
+
Wonderful, you've encoded the second measure! Now we will increase the level of difficulty a little bit more: the final two measures are waiting. But don't worry: this is the most ambitious step of this tutorial. Promise!
+
+
To encode the final two measures you will need to know about one more element: A pause is encoded with a <rest> element having a @dur attribute similar to the <note> element. But, of course, a <rest> has neither @pname nor @oct attributes. You can ignore the additional elements, such as dynamics, slurs or accents at this point as they will be addressed separately in the next final steps.
+
+
Please encode the final two measures (@n=3 & @n=4) of the example in the editor below. Add <measure>, <staff> and <layer> elements as well as the corresponding <note>, <beam> or <rest> elements. Keep in mind how the <beam> element is used to group the corresponding <note> elements.
+
+
Again, there is no prefilled content in the editor box for this step. If you feel lost or unsure at any time, try to follow the hints that are displayed below the editor box. That should guide you through this task.
+
diff --git a/_tutorials-BA/102_incipit/step-09/102_incipit_step-09-prefill.xml b/_tutorials-BA/102_incipit/step-09/102_incipit_step-09-prefill.xml
new file mode 100644
index 00000000..44fbfea5
--- /dev/null
+++ b/_tutorials-BA/102_incipit/step-09/102_incipit_step-09-prefill.xml
@@ -0,0 +1 @@
+
diff --git a/_tutorials-BA/102_incipit/step-10/102_incipit_step-10-desc.html b/_tutorials-BA/102_incipit/step-10/102_incipit_step-10-desc.html
new file mode 100644
index 00000000..14adde2b
--- /dev/null
+++ b/_tutorials-BA/102_incipit/step-10/102_incipit_step-10-desc.html
@@ -0,0 +1,14 @@
+
+
Step ten: adding the articulation signs to your encoding of the example.
+
+
Awesome! You have encoded the whole melodic line of the example. Now, let's consider the missing additional elements, such as dynamics, slurs or accents, step by step.
+
+
Articulations, i.e. indications of how to play a note or chord, can be encoded with <artic> elements that are applied as children to <note> elements.
+ The following attributes on <artic> should be used in this tutorial step:
+
+
@artic (articulation type) – the type of articulation mark, e.g.: accent “acc”, staccato “stacc”, tenuto “ten”, use “acc” here,
+
@place – position of the articulation sign, “above” or “below” the staff, use “above” here.
+
+
+
Please find the <note> elements in the example to which articulations are assigned (there are musical accents on the dotted quarter notes in measure 1 & 2 as well as on the quarter note in measure 3). Add a child element <artic> to these <note> elements and apply the corresponding attributes (@artic, @place).
Step eleven: adding the dynamic marking to your encoding of the example.
+
+
Dynamics are defined with a <dynam> element. The <dynam> element may be used for instantaneous or continuous textual dynamics, e.g. “p”, “mf”, or “cresc. poco a poco”. These are placed as plain text between the opening and closing tag of the <dynam> element, like <dynam>pp</dynam>.
+
+
Unlike articulation signs, the <dynam> element is a so-called control event which groups elements (such as dynamics, ties, phrase marks, pedal marks, etc.), that depend upon other events, such as notes or rests, for their validity. In general, control events are not encoded as child elements of the corresponding events they are meant to control. In practice, it means that they are placed outside the staff elements in most cases.
+
+
There are different options to indicate the reference to a <note> or <rest> (or any other event) from a control event like <dynam>:
+
+
+
At first, the <staff> to which the control event shall be applied, can be referenced by a @staff attribute.
+
Furthermore, the starting point of a dynamic marking must be indicated either by a startid, tstamp, tstamp.ges, or tstamp.real attribute. The ending point may be indicated by either a dur, dur.ges, endid, or tstamp2 attribute. It is a semantic error not to specify a starting point attribute.
+
+
+
In this example, the @tstamp attribute is used to indicate the starting position of the dynamic marking. @tstamp can be used to encode the onset time in terms of musical time, i.e. beats, as expressed in the written time signature.
+
+
The following attributes are the ones to be used here within <dynam>:
+
+
@staff – the identification number of the staff to which an element is applied, e.g. “1” in this case
+
@tstamp (time stamp) – the onset time in terms of musical time, i.e. beats, e.g. “1”, “2.5”
+
@place – position of the dynamic marking, “above” or “below” the staff.
+
+
+
Please find the <note> elements in the example to which dynamics are assigned. Add a sibling element <dynam> to the corresponding <staff> element and apply the attributes in question (@staff, @tstamp, @place). Do not forget to include the ff sign between the opening and closing tag of <dynam>.
Step twelve: adding the last missing detail of the example, the slur in the third measure.
+
+
There are two different ways to encode a slur in MEI:
+
+
@slur attribute on <note> or <chord> with a value of i=initial, m=medial or
+ t=terminal.
+
A separate <slur> element.
+
+
+
In this last step, you will use the second approach: Like dynamics, <slur> elements are control events. They are not encoded as child elements of the corresponding events that they are meant to control but are placed in most cases outside the staff elements.
+
+
To indicate the starting point and end point of the slur, it is possible to apply a reference to the corresponding @xml:id of a <note> or
+ <chord> element. @xml:ids are identifiers with an arbitrary but unique character sequence that regularize the naming of an element throughout a document
+ and thus facilitate building links between elements and other resources. For <slur>s, a reference to the @xml:id of an element can be given via the
+ attributes @startid and @endid.
+
+
Along with @startid and @endid, the following attributes should be used in this step:
+
+
@staff – the identification number of the staff to which an element is applied, e.g. “1” in this case,
+
@curvedir (curve direction) – describes a curve with a generic term indicating the direction of curvature: “above”, “below” or “mixed”,
+
@startid – reference to the xml:id of the start note of the slur, in the form: #xml:id (note the hash #),
+
@endid – reference to the xml:id of the ending note of the slur, in the form: #xml:id (note the hash #).
+
+
+
Please identify the first and the last note to which the slur is attached (inside the first <beam> element of measure 3) and add @xml:ids to both <note> elements. Set a unique value for each @xml:id, for this example you can use the values: “d1e4614”, “d1e4615”. Add a <slur> control element after the closing tag of <staff> element and apply the corresponding attributes.
+
diff --git a/_tutorials-BA/102_incipit/step-12/102_incipit_step-12-prefill.xml b/_tutorials-BA/102_incipit/step-12/102_incipit_step-12-prefill.xml
new file mode 100644
index 00000000..e2b89b37
--- /dev/null
+++ b/_tutorials-BA/102_incipit/step-12/102_incipit_step-12-prefill.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/_tutorials-BA/103_chords/103_Chords.md b/_tutorials-BA/103_chords/103_Chords.md
new file mode 100644
index 00000000..80cb7160
--- /dev/null
+++ b/_tutorials-BA/103_chords/103_Chords.md
@@ -0,0 +1,7 @@
+---
+layout: tutorials
+type: tutorial
+name: "BEGINNERS: Chords"
+fullname: "A short tutorial about chords in MEI"
+data: "103_chords.json"
+---
diff --git a/_tutorials-BA/103_chords/103_chords.json b/_tutorials-BA/103_chords/103_chords.json
new file mode 100644
index 00000000..f29d46ff
--- /dev/null
+++ b/_tutorials-BA/103_chords/103_chords.json
@@ -0,0 +1,203 @@
+{
+ "steps": [
+ {
+ "label":"Welcome to MEI",
+ "descFile": "103_chords_step-00-desc.html"
+ },
+ {
+ "label":"Preparation",
+ "editorLines":3,
+ "descFile": "103_chords_step-01-desc.html",
+ "prefillFile": "103_chords_step-01-prefill.xml",
+ "xmlFile": "103_chords_step-01.xml",
+ "xpaths": [
+ {"rule":"count(//mei:note) = 3", "renderanyway": false, "hint": "You need three note elements."},
+ {"rule":"count(//mei:note[1]/@*) = 3 and //mei:note[1]/@pname and //mei:note[1]/@oct and //mei:note[1]/@dur", "renderanyway": false, "hint": "You need three attributes on the first note (@pname, @oct, and @dur)."},
+ {"rule":"count(//mei:note[2]/@*) = 3 and //mei:note[2]/@pname and //mei:note[2]/@oct and //mei:note[2]/@dur", "renderanyway": false, "hint": "You need three attributes on the second note (@pname, @oct, and @dur)."},
+ {"rule":"count(//mei:note[3]/@*) = 3 and //mei:note[3]/@pname and //mei:note[3]/@oct and //mei:note[3]/@dur", "renderanyway": false, "hint": "You need three attributes on the third note (@pname, @oct, and @dur)."},
+ {"rule":"//mei:note/@pname", "renderanyway": false, "hint": "The @pname attribute allows values from 'a' to 'g'."},
+ {"rule":"//mei:note/@oct", "renderanyway": false, "hint": "The @oct attribute requires integers."},
+ {"rule":"//mei:note/@dur", "renderanyway": false, "hint": "The @dur attribute allows values such as '1', '2', '4', '8'…"},
+ {"rule":"//mei:note[1]/@pname = 'e'", "renderanyway": true, "hint": "You need a @pname attribute with a value of e on the first note element."},
+ {"rule":"//mei:note[1]/@oct = '4'", "renderanyway": true, "hint": "You need an @oct attribute with a value of 4 on the first note element."},
+ {"rule":"//mei:note[1]/@dur = '4'", "renderanyway": true, "hint": "You need a @dur attribute with a value of 4 on the first note element."},
+ {"rule":"//mei:note[2]/@pname = 'g'", "renderanyway": true, "hint": "You need a @pname attribute with a value of g on the second note element."},
+ {"rule":"//mei:note[2]/@oct = '4'", "renderanyway": true, "hint": "You need an @oct attribute with a value of 4 on the second note element."},
+ {"rule":"//mei:note[2]/@dur = '4'", "renderanyway": true, "hint": "You need a @dur attribute with a value of 4 on the second note element."},
+ {"rule":"//mei:note[3]/@pname = 'c'", "renderanyway": true, "hint": "You need a @pname attribute with a value of c on the third note element."},
+ {"rule":"//mei:note[3]/@oct = '5'", "renderanyway": true, "hint": "You need an @oct attribute with a value of 5 on the third note element."},
+ {"rule":"//mei:note[3]/@dur = '4'", "renderanyway": true, "hint": "You need a @dur attribute with a value of 4 on the third note element."}
+ ]
+ },
+ {
+ "label":"First Chord",
+ "editorLines":5,
+ "descFile": "103_chords_step-02-desc.html",
+ "prefillFile": "103_chords_step-02-prefill.xml",
+ "xmlFile": "103_chords_step-02.xml",
+ "xpaths": [
+ {"rule":"count(//mei:note) = 3", "renderanyway": false, "hint": "You need three note elements."},
+ {"rule":"//mei:note[1]/@pname and //mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the first note (@pname, @oct)."},
+ {"rule":"//mei:note[2]/@pname and //mei:note[2]/@oct", "renderanyway": true, "hint": "You need two attributes on the second note (@pname, @oct)."},
+ {"rule":"//mei:note[3]/@pname and //mei:note[3]/@oct", "renderanyway": true, "hint": "You need two attributes on the third note (@pname, @oct)."},
+ {"rule":"//mei:note/@pname", "renderanyway": false, "hint": "The @pname attribute allows values from 'a' to 'g'."},
+ {"rule":"//mei:note/@oct", "renderanyway": false, "hint": "The @oct attribute requires integers."},
+ {"rule":"//mei:note[@pname = 'e' and @oct = '4']", "renderanyway": true, "hint": "You need a note with a @pname attribute with a value of e and an @oct attribute with a value of 4."},
+ {"rule":"//mei:note[@pname = 'g' and @oct = '4']", "renderanyway": true, "hint": "You need a note with a @pname attribute with a value of g and an @oct attribute with a value of 4."},
+ {"rule":"//mei:note[@pname = 'c' and @oct = '5']", "renderanyway": true, "hint": "You need a note with a @pname attribute with a value of c and an @oct attribute with a value of 5."},
+ {"rule":"count(//mei:chord) = 1", "renderanyway": false, "hint": "You need one chord element."},
+ {"rule":"//mei:chord/mei:note", "renderanyway": false, "hint": "chord element has to enclose all the note elements."},
+ {"rule":"count(//mei:note[1]/@*) = 2", "renderanyway": true, "hint": "You need only two attributes on the first note (@pname, @oct)."},
+ {"rule":"count(//mei:note[2]/@*) = 2", "renderanyway": true, "hint": "You need only two attributes on the second note (@pname, @oct)."},
+ {"rule":"count(//mei:note[3]/@*) = 2", "renderanyway": true, "hint": "You need only two attributes on the third note (@pname, @oct)."},
+ {"rule":"count(//mei:chord/@*) = 1 and //mei:chord/@dur", "renderanyway": true, "hint": "You need one attribute on the chord (@dur)."},
+ {"rule":"//mei:chord/@dur", "renderanyway": true, "hint": "The @dur attribute allows values such as '1', '2', '4', '8'…"},
+ {"rule":"//mei:chord/@dur = '4'", "renderanyway": true, "hint": "You need a @dur attribute with a value of 4 on the chord element."}
+ ]
+ },
+ {
+ "label":"Simple Chord Progression",
+ "editorLines":20,
+ "descFile": "103_chords_step-03-desc.html",
+ "prefillFile": "103_chords_step-03-prefill.xml",
+ "xmlFile": "103_chords_step-03.xml",
+ "xpaths": [
+ {"rule":"count(//mei:chord) = 4", "renderanyway": true, "hint": "You need four chord elements."},
+ {"rule":"count(//mei:chord[1]/@*) = 1 and //mei:chord[1]/@dur", "renderanyway": true, "hint": "You need one attribute on the first chord (@dur)."},
+ {"rule":"//mei:chord[1]/@dur = '4'", "renderanyway": true, "hint": "You need a @dur attribute with a value of 4 on the first chord element."},
+ {"rule":"count(//mei:chord[2]/@*) = 1 and //mei:chord[2]/@dur", "renderanyway": true, "hint": "You need one attribute on the second chord (@dur)."},
+ {"rule":"//mei:chord[2]/@dur = '4'", "renderanyway": true, "hint": "You need a @dur attribute with a value of 4 on the second chord element."},
+ {"rule":"count(//mei:chord[3]/@*) = 1 and //mei:chord[3]/@dur", "renderanyway": true, "hint": "You need one attribute on the third chord (@dur)."},
+ {"rule":"//mei:chord[3]/@dur = '4'", "renderanyway": true, "hint": "You need a @dur attribute with a value of 4 on the third chord element."},
+ {"rule":"count(//mei:chord[4]/@*) = 1 and //mei:chord[4]/@dur", "renderanyway": true, "hint": "You need one attribute on the last chord (@dur)."},
+ {"rule":"//mei:chord[4]/@dur = '4'", "renderanyway": true, "hint": "You need a @dur attribute with a value of 4 on the last chord element."},
+
+ {"rule":"count(//mei:chord[1]/mei:note) = 3", "renderanyway": true, "hint": "You need three note elements for the first chord."},
+ {"rule":"count(//mei:chord[1]/mei:note[1]/@*) = 2 and //mei:chord[1]/mei:note[1]/@pname and //mei:chord[1]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the first note (@pname, @oct) of the first chord."},
+ {"rule":"//mei:chord[1]/mei:note[@pname = 'e' and @oct = '4']", "renderanyway": true, "hint": "In the first chord, you need a note with a @pname attribute with a value of e and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[1]/mei:note[2]/@*) = 2 and //mei:chord[1]/mei:note[2]/@pname and //mei:chord[1]/mei:note[2]/@oct", "renderanyway": true, "hint": "You need two attributes on the second note (@pname, @oct) of the first chord."},
+ {"rule":"//mei:chord[1]/mei:note[@pname = 'g' and @oct = '4']", "renderanyway": true, "hint": "In the first chord, you need a note with a @pname attribute with a value of g and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[1]/mei:note[3]/@*) = 2 and //mei:chord[1]/mei:note[3]/@pname and //mei:chord[1]/mei:note[3]/@oct", "renderanyway": true, "hint": "You need two attributes on the third note (@pname, @oct) of the first chord."},
+ {"rule":"//mei:chord[1]/mei:note[@pname = 'c' and @oct = '5']", "renderanyway": true, "hint": "In the first chord, you need a note with a @pname attribute with a value of c and an @oct attribute with a value of 5."},
+
+
+ {"rule":"count(//mei:chord[2]/mei:note) = 3", "renderanyway": true, "hint": "You need three note elements for the second chord."},
+ {"rule":"count(//mei:chord[2]/mei:note[1]/@*) = 2 and //mei:chord[2]/mei:note[1]/@pname and //mei:chord[2]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the first note (@pname, @oct) of the second chord."},
+ {"rule":"//mei:chord[2]/mei:note[@pname = 'f' and @oct = '4']", "renderanyway": true, "hint": "In the second chord, you need a @pname attribute with a value of f and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[2]/mei:note[2]/@*) = 2 and //mei:chord[2]/mei:note[2]/@pname and //mei:chord[2]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the second note (@pname, @oct) of the second chord."},
+ {"rule":"//mei:chord[2]/mei:note[@pname = 'a' and @oct = '4']", "renderanyway": true, "hint": "In the second chord, you need a @pname attribute with a value of a and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[2]/mei:note[3]/@*) = 2 and //mei:chord[2]/mei:note[3]/@pname and //mei:chord[2]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the third note (@pname, @oct) of the second chord."},
+ {"rule":"//mei:chord[2]/mei:note[@pname = 'c' and @oct = '5']", "renderanyway": true, "hint": "In the second chord, you need a @pname attribute with a value of c and an @oct attribute with a value of 5."},
+
+
+ {"rule":"count(//mei:chord[3]/mei:note) = 3", "renderanyway": true, "hint": "You need three note elements for the third chord."},
+ {"rule":"count(//mei:chord[3]/mei:note[1]/@*) = 2 and //mei:chord[3]/mei:note[1]/@pname and //mei:chord[3]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the first note (@pname, @oct) of the third chord."},
+ {"rule":"//mei:chord[3]/mei:note[@pname = 'd' and @oct = '4']", "renderanyway": true, "hint": "In the third chord, you need a @pname attribute with a value of d and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[3]/mei:note[2]/@*) = 2 and //mei:chord[3]/mei:note[2]/@pname and //mei:chord[3]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the second note (@pname, @oct) of the third chord."},
+ {"rule":"//mei:chord[3]/mei:note[@pname = 'g' and @oct = '4']", "renderanyway": true, "hint": "In the third chord, you need a @pname attribute with a value of g and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[3]/mei:note[3]/@*) = 2 and //mei:chord[3]/mei:note[3]/@pname and //mei:chord[3]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the third note (@pname, @oct) of the third chord."},
+ {"rule":"//mei:chord[3]/mei:note[@pname = 'b' and @oct = '4']", "renderanyway": true, "hint": "In the third chord, you need a @pname attribute with a value of b and an @oct attribute with a value of 4."},
+
+ {"rule":"count(//mei:chord[4]/mei:note) = 3", "renderanyway": true, "hint": "You need three note elements for the fourth chord."},
+ {"rule":"count(//mei:chord[4]/mei:note[1]/@*) = 2 and //mei:chord[4]/mei:note[1]/@pname and //mei:chord[4]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the first note (@pname, @oct) of the fourth chord."},
+ {"rule":"//mei:chord[4]/mei:note[@pname = 'e' and @oct = '4']", "renderanyway": true, "hint": "In the fourth chord, you need a @pname attribute with a value of e and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[4]/mei:note[2]/@*) = 2 and //mei:chord[4]/mei:note[2]/@pname and //mei:chord[4]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the second note (@pname, @oct) of the fourth chord."},
+ {"rule":"//mei:chord[4]/mei:note[@pname = 'g' and @oct = '4']", "renderanyway": true, "hint": "In the fourth chord, you need a @pname attribute with a value of g and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[4]/mei:note[3]/@*) = 2 and //mei:chord[4]/mei:note[3]/@pname and //mei:chord[4]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the third note (@pname, @oct) of the fourth chord."},
+ {"rule":"//mei:chord[4]/mei:note[@pname = 'c' and @oct = '5']", "renderanyway": true, "hint": "In the fourth chord, you need a @pname attribute with a value of c and an @oct attribute with a value of 5."}
+ ]
+ },
+ {
+ "label":"Extended Chord Progression",
+ "editorLines":35,
+ "descFile": "103_chords_step-04-desc.html",
+ "prefillFile": "103_chords_step-04-prefill.xml",
+ "xmlFile": "103_chords_step-04.xml",
+ "xpaths": [
+ {"rule":"count(//mei:chord) = 7", "renderanyway": true, "hint": "You need seven chord elements."},
+ {"rule":"count(//mei:chord[1]/@*) = 2 and //mei:chord[1]/@dur and //mei:chord[1]/@dots", "renderanyway": true, "hint": "You need two attributes on the first chord (@dur, @dots)."},
+ {"rule":"//mei:chord[1]/@dur = '4'", "renderanyway": true, "hint": "You need a @dur attribute with a value of 4 on the first chord element."},
+ {"rule":"//mei:chord[1]/@dots = '1'", "renderanyway": true, "hint": "You need a @dots attribute with a value of 1 on the first chord element."},
+ {"rule":"count(//mei:chord[2]/@*) = 1 and //mei:chord[2]/@dur", "renderanyway": true, "hint": "You need one attribute on the second chord (@dur)."},
+ {"rule":"//mei:chord[2]/@dur = '8'", "renderanyway": true, "hint": "You need a @dur attribute with a value of 8 on the second chord element."},
+ {"rule":"count(//mei:chord[3]/@*) = 1 and //mei:chord[3]/@dur", "renderanyway": true, "hint": "You need one attribute on the third chord (@dur)."},
+ {"rule":"//mei:chord[3]/@dur = '4'", "renderanyway": true, "hint": "You need a @dur attribute with a value of 4 on the third chord element."},
+ {"rule":"count(//mei:chord[4]/@*) = 1 and //mei:chord[4]/@dur", "renderanyway": true, "hint": "You need one attribute on the fourth chord (@dur)."},
+ {"rule":"//mei:chord[4]/@dur = '4'", "renderanyway": true, "hint": "You need a @dur attribute with a value of 4 on the fourth chord element."},
+ {"rule":"count(//mei:chord[5]/@*) = 1 and //mei:chord[5]/@dur", "renderanyway": true, "hint": "You need one attribute on the fifth chord (@dur)."},
+ {"rule":"//mei:chord[5]/@dur = '4'", "renderanyway": true, "hint": "You need a @dur attribute with a value of 4 on the fifth chord element."},
+ {"rule":"count(//mei:chord[6]/@*) = 1 and //mei:chord[6]/@dur", "renderanyway": true, "hint": "You need one attribute on the sixth chord (@dur)."},
+ {"rule":"//mei:chord[6]/@dur = '4'", "renderanyway": true, "hint": "You need a @dur attribute with a value of 4 on the sixth chord element."},
+ {"rule":"count(//mei:chord[7]/@*) = 1 and //mei:chord[7]/@dur", "renderanyway": true, "hint": "You need one attribute on the last chord (@dur)."},
+ {"rule":"//mei:chord[7]/@dur = '2'", "renderanyway": true, "hint": "You need a @dur attribute with a value of 2 on the last chord element."},
+
+ {"rule":"count(//mei:chord[1]/mei:note) = 3", "renderanyway": true, "hint": "You need three note elements for the first chord."},
+ {"rule":"count(//mei:chord[1]/mei:note[1]/@*) = 2 and //mei:chord[1]/mei:note[1]/@pname and //mei:chord[1]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the first note (@pname, @oct) of the first chord."},
+ {"rule":"//mei:chord[1]/mei:note[@pname = 'g' and @oct = '4']", "renderanyway": true, "hint": "In the first chord, you need a note with a @pname attribute with a value of g and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[1]/mei:note[2]/@*) = 2 and //mei:chord[1]/mei:note[2]/@pname and //mei:chord[1]/mei:note[2]/@oct", "renderanyway": true, "hint": "You need two attributes on the second note (@pname, @oct) of the first chord."},
+ {"rule":"//mei:chord[1]/mei:note[@pname = 'c' and @oct = '5']", "renderanyway": true, "hint": "In the first chord, you need a note with a @pname attribute with a value of c and an @oct attribute with a value of 5."},
+ {"rule":"count(//mei:chord[1]/mei:note[3]/@*) = 2 and //mei:chord[1]/mei:note[3]/@pname and //mei:chord[1]/mei:note[3]/@oct", "renderanyway": true, "hint": "You need two attributes on the third note (@pname, @oct) of the first chord."},
+ {"rule":"//mei:chord[1]/mei:note[@pname = 'e' and @oct = '5']", "renderanyway": true, "hint": "In the first chord, you need a note with a @pname attribute with a value of e and an @oct attribute with a value of 5."},
+
+ {"rule":"count(//mei:chord[2]/mei:note) = 3", "renderanyway": true, "hint": "You need three note elements for the second chord."},
+ {"rule":"count(//mei:chord[2]/mei:note[1]/@*) = 2 and //mei:chord[2]/mei:note[1]/@pname and //mei:chord[2]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the first note (@pname, @oct) of the second chord."},
+ {"rule":"//mei:chord[2]/mei:note[@pname = 'f' and @oct = '4']", "renderanyway": true, "hint": "In the second chord, you need a @pname attribute with a value of f and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[2]/mei:note[2]/@*) = 2 and //mei:chord[2]/mei:note[2]/@pname and //mei:chord[2]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the second note (@pname, @oct) of the second chord."},
+ {"rule":"//mei:chord[2]/mei:note[@pname = 'b' and @oct = '4']", "renderanyway": true, "hint": "In the second chord, you need a @pname attribute with a value of b and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[2]/mei:note[3]/@*) = 2 and //mei:chord[2]/mei:note[3]/@pname and //mei:chord[2]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the third note (@pname, @oct) of the second chord."},
+ {"rule":"//mei:chord[2]/mei:note[@pname = 'd' and @oct = '5']", "renderanyway": true, "hint": "In the second chord, you need a @pname attribute with a value of d and an @oct attribute with a value of 5."},
+
+ {"rule":"count(//mei:chord[3]/mei:note) = 3", "renderanyway": true, "hint": "You need three note elements for the third chord."},
+ {"rule":"count(//mei:chord[3]/mei:note[1]/@*) = 2 and //mei:chord[3]/mei:note[1]/@pname and //mei:chord[3]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the first note (@pname, @oct) of the third chord."},
+ {"rule":"//mei:chord[3]/mei:note[@pname = 'e' and @oct = '4']", "renderanyway": true, "hint": "In the third chord, you need a @pname attribute with a value of e and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[3]/mei:note[2]/@*) = 2 and //mei:chord[3]/mei:note[2]/@pname and //mei:chord[3]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the second note (@pname, @oct) of the third chord."},
+ {"rule":"//mei:chord[3]/mei:note[@pname = 'g' and @oct = '4']", "renderanyway": true, "hint": "In the third chord, you need a @pname attribute with a value of g and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[3]/mei:note[3]/@*) = 2 and //mei:chord[3]/mei:note[3]/@pname and //mei:chord[3]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the third note (@pname, @oct) of the third chord."},
+ {"rule":"//mei:chord[3]/mei:note[@pname = 'c' and @oct = '5']", "renderanyway": true, "hint": "In the third chord, you need a @pname attribute with a value of c and an @oct attribute with a value of 5."},
+
+ {"rule":"count(//mei:chord[4]/mei:note) = 3", "renderanyway": true, "hint": "You need three note elements for the fourth chord."},
+ {"rule":"count(//mei:chord[4]/mei:note[1]/@*) = 2 and //mei:chord[4]/mei:note[1]/@pname and //mei:chord[4]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the first note (@pname, @oct) of the fourth chord."},
+ {"rule":"//mei:chord[4]/mei:note[@pname = 'f' and @oct = '4']", "renderanyway": true, "hint": "In the fourth chord, you need a @pname attribute with a value of f and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[4]/mei:note[2]/@*) = 2 and //mei:chord[4]/mei:note[2]/@pname and //mei:chord[4]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the second note (@pname, @oct) of the fourth chord."},
+ {"rule":"//mei:chord[4]/mei:note[@pname = 'b' and @oct = '4']", "renderanyway": true, "hint": "In the fourth chord, you need a @pname attribute with a value of b and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[4]/mei:note[3]/@*) = 2 and //mei:chord[4]/mei:note[3]/@pname and //mei:chord[4]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the third note (@pname, @oct) of the fourth chord."},
+ {"rule":"//mei:chord[4]/mei:note[@pname = 'd' and @oct = '5']", "renderanyway": true, "hint": "In the fourth chord, you need a @pname attribute with a value of d and an @oct attribute with a value of 5."},
+
+ {"rule":"count(//mei:chord[5]/mei:note) = 3", "renderanyway": true, "hint": "You need three note elements for the fifth chord."},
+ {"rule":"count(//mei:chord[5]/mei:note[1]/@*) = 2 and //mei:chord[5]/mei:note[1]/@pname and //mei:chord[5]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the first note (@pname, @oct) of the fifth chord."},
+ {"rule":"//mei:chord[5]/mei:note[@pname = 'g' and @oct = '4']", "renderanyway": true, "hint": "In the fifth chord, you need a note with a @pname attribute with a value of g and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[5]/mei:note[2]/@*) = 2 and //mei:chord[5]/mei:note[2]/@pname and //mei:chord[5]/mei:note[2]/@oct", "renderanyway": true, "hint": "You need two attributes on the second note (@pname, @oct) of the fifth chord."},
+ {"rule":"//mei:chord[5]/mei:note[@pname = 'c' and @oct = '5']", "renderanyway": true, "hint": "In the fifth chord, you need a note with a @pname attribute with a value of c and an @oct attribute with a value of 5."},
+ {"rule":"count(//mei:chord[5]/mei:note[3]/@*) = 2 and //mei:chord[5]/mei:note[3]/@pname and //mei:chord[5]/mei:note[3]/@oct", "renderanyway": true, "hint": "You need two attributes on the third note (@pname, @oct) of the fifth chord."},
+ {"rule":"//mei:chord[5]/mei:note[@pname = 'e' and @oct = '5']", "renderanyway": true, "hint": "In the fifth chord, you need a note with a @pname attribute with a value of e and an @oct attribute with a value of 5."},
+
+ {"rule":"count(//mei:chord[6]/mei:note) = 3", "renderanyway": true, "hint": "You need three note elements for the sixth chord."},
+ {"rule":"count(//mei:chord[6]/mei:note[1]/@*) = 2 and //mei:chord[6]/mei:note[1]/@pname and //mei:chord[6]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the first note (@pname, @oct) of the sixth chord."},
+ {"rule":"//mei:chord[6]/mei:note[@pname = 'g' and @oct = '4']", "renderanyway": true, "hint": "In the sixth chord, you need a note with a @pname attribute with a value of g and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[6]/mei:note[2]/@*) = 2 and //mei:chord[6]/mei:note[2]/@pname and //mei:chord[6]/mei:note[2]/@oct", "renderanyway": true, "hint": "You need two attributes on the second note (@pname, @oct) of the sixth chord."},
+ {"rule":"//mei:chord[6]/mei:note[@pname = 'c' and @oct = '5']", "renderanyway": true, "hint": "In the sixth chord, you need a note with a @pname attribute with a value of c and an @oct attribute with a value of 5."},
+ {"rule":"count(//mei:chord[6]/mei:note[3]/@*) = 2 and //mei:chord[6]/mei:note[3]/@pname and //mei:chord[6]/mei:note[3]/@oct", "renderanyway": true, "hint": "You need two attributes on the third note (@pname, @oct) of the sixth chord."},
+ {"rule":"//mei:chord[6]/mei:note[@pname = 'e' and @oct = '5']", "renderanyway": true, "hint": "In the sixth chord, you need a note with a @pname attribute with a value of e and an @oct attribute with a value of 5."},
+
+ {"rule":"count(//mei:chord[7]/mei:note) = 3", "renderanyway": true, "hint": "You need three note elements for the last chord."},
+ {"rule":"count(//mei:chord[7]/mei:note[1]/@*) = 2 and //mei:chord[7]/mei:note[1]/@pname and //mei:chord[7]/mei:note[1]/@oct", "renderanyway": true, "hint": "You need two attributes on the first note (@pname, @oct) of the last chord."},
+ {"rule":"//mei:chord[7]/mei:note[@pname = 'g' and @oct = '4']", "renderanyway": true, "hint": "In the last chord, you need a note with a @pname attribute with a value of g and an @oct attribute with a value of 4."},
+ {"rule":"count(//mei:chord[7]/mei:note[2]/@*) = 2 and //mei:chord[7]/mei:note[2]/@pname and //mei:chord[7]/mei:note[2]/@oct", "renderanyway": true, "hint": "You need two attributes on the second note (@pname, @oct) of the last chord."},
+ {"rule":"//mei:chord[7]/mei:note[@pname = 'c' and @oct = '5']", "renderanyway": true, "hint": "In the last chord, you need a note with a @pname attribute with a value of c and an @oct attribute with a value of 5."},
+ {"rule":"count(//mei:chord[7]/mei:note[3]/@*) = 2 and //mei:chord[7]/mei:note[3]/@pname and //mei:chord[7]/mei:note[3]/@oct", "renderanyway": true, "hint": "You need two attributes on the third note (@pname, @oct) of the last chord."},
+ {"rule":"//mei:chord[7]/mei:note[@pname = 'e' and @oct = '5']", "renderanyway": true, "hint": "In the last chord, you need a note with a @pname attribute with a value of e and an @oct attribute with a value of 5."}
+ ]
+ }
+ ],
+ "end":"103_chords_end.html",
+ "resp":[
+ {
+ "name":"Stefan Münnich",
+ "affiliation":"Anton Webern Gesamtausgabe | University of Basel"
+ },
+ {
+ "name":"Johannes Kepper",
+ "affiliation":"Beethovens Werkstatt | Universität Paderborn"
+ }
+ ]
+}
diff --git a/_tutorials-BA/103_chords/103_chords_end.html b/_tutorials-BA/103_chords/103_chords_end.html
new file mode 100644
index 00000000..955f6415
--- /dev/null
+++ b/_tutorials-BA/103_chords/103_chords_end.html
@@ -0,0 +1,23 @@
+
+
Congratulations!
+
You just finished this basic tutorial about chords in MEI, and you should be able to encode some simple chord
+ progressions with MEI already.
+
+
+ Of course, a lot more is needed for a comprehensive MEI file – we left out all structural information
+ about measures and staves, and you also need to learn how to set up meter, key, and clefs. As next steps with
+ MEI, we would like to recommend our tutorial on rests.
+ Of course, you can always come back to these (or even this one) when you would like to remind yourself how to do
+ certain things in MEI.
+
+
+ As soon as you have familiarized yourself with MEI to some degree, we invite you to share your experience with
+ the MEI Community
+ and write a tutorial on an aspect of MEI that you're particularly interested in. You don't have to be an expert
+ for this – it's good to have tutorials on different levels. Often a tutorial written by other beginners which
+ just mastered a task is easier to follow than a guide written by someone who's not seeing the problem at all.
+ We do have a tutorial on how to write
+ tutorials, and there are templates to follow. It's that easy to become an active member of the MEI
+ Community :-)
+
+
diff --git a/_tutorials-BA/103_chords/step-00/103_chords_step-00-desc.html b/_tutorials-BA/103_chords/step-00/103_chords_step-00-desc.html
new file mode 100644
index 00000000..c8811583
--- /dev/null
+++ b/_tutorials-BA/103_chords/step-00/103_chords_step-00-desc.html
@@ -0,0 +1,21 @@
+
+
+ In this tutorial, you will learn how to encode chords in MEI.
+
+
+ Since the concept of a chord is strongly based on notes, we recommend that you familiarize yourself with the
+ encoding of notes before this tutorial, e.g. in our
+ Quickstart tutorial.
+
+
+ The code you write will be immediately rendered, and the rendering will respond to your changes. That way, you
+ will get a feeling on how the different parameters interact.
+
+
+ After you have finished this tutorial, you may want to do other tutorials, which will introduce you other
+ important aspects of MEI. These tutorials also serve as simple reference to MEI – you can always go back to them.
+
+
+ In order to get started, please hit the "continue" button on the lower right of this paragraph.
+
+
diff --git a/_tutorials-BA/103_chords/step-01/103_chords_step-01-desc.html b/_tutorials-BA/103_chords/step-01/103_chords_step-01-desc.html
new file mode 100644
index 00000000..3983b6e4
--- /dev/null
+++ b/_tutorials-BA/103_chords/step-01/103_chords_step-01-desc.html
@@ -0,0 +1,38 @@
+
+
+ Step one: provide some notes for a chord.
+
+
+ In MEI, the notion of a chord means the "simultaneous sounding of two or more notes in the same layer with the
+ same duration" (see Element specification).
+ Thus, a chord is made up of two or more note elements that belong to the same voice (layer) and have an identical
+ rhythmical structure (duration). (There are cases where you don't want to have the same duration on every note
+ of a chord, but these are not part of this basic tutorial.)
+
+
+ To encode such a "simultaneous sounding", the <chord> element is used in MEI. Its use is pretty
+ straightforward: Multiple <note> elements within the same layer are enclosed by a <chord>
+ element and the duration attribute (@dur) is moved from the <note>s to the <chord>
+ element (since the duration is the same for all notes). However, whether you write an outer <chord>
+ element first to add some inner <note> elements, or whether you start with the <note>s
+ and then enclose them in a <chord> element, does not actually matter in practice.
+
+
+ For this tutorial, let's stick to the second approach: This means, we need some notes first.
+
+
+ In the editor below, please enter the following three <note> elements:
+
+
+
<note pname="e" oct="4" dur="4"/>
+
<note pname="g" oct="4" dur="4"/>
+
<note pname="c" oct="5" dur="4"/>
+
+
+
+ You should then see the three notes rendered sequentially. Not much of a chord, actually. But don't worry: We will
+ care about that right away in the next step. Until then, you may play a little bit with the attribute values to
+ see how they influence the rendering. You will also see hints on how to write the correct code. Whenever you're
+ ready, make sure to have the correct code in the editor, and then hit the "continue" button on the lower right.
+
+
diff --git a/_tutorials-BA/103_chords/step-01/103_chords_step-01-prefill.xml b/_tutorials-BA/103_chords/step-01/103_chords_step-01-prefill.xml
new file mode 100644
index 00000000..b28124ba
--- /dev/null
+++ b/_tutorials-BA/103_chords/step-01/103_chords_step-01-prefill.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/_tutorials-BA/103_chords/step-02/103_chords_step-02-desc.html b/_tutorials-BA/103_chords/step-02/103_chords_step-02-desc.html
new file mode 100644
index 00000000..db4c00be
--- /dev/null
+++ b/_tutorials-BA/103_chords/step-02/103_chords_step-02-desc.html
@@ -0,0 +1,22 @@
+
+
+ Step two: encode a simple chord (triad).
+
+
+ Well done! Now it's time to make a <chord> out of these three <note>s. As mentioned
+ in the previous step, you should enclose the note elements in a chord element and move the duration attributes
+ from the notes to the chord.
+
+
+ In the editor below, enclose the three <note> elements in a <chord> element (i.e. insert
+ the opening tag of <chord> before the first note and the closing tag after the last one). The three
+ single notes should now be rendered not sequentially, but vertically aligned, but they lack a correct duration
+ yet. So remove the duration attributes from all the notes and add one to the <chord> instead. Keep
+ the duration of a quarter (@dur="4").
+
+
+ You should then see the chord rendered. Again, you may play a little bit with the attribute values to see how they
+ influence the rendering. You will also see hints on how to write the correct code. Whenever you're ready, make
+ sure to have the correct code in the editor, and then hit the "continue" button on the lower right.
+
+ Step three: encode a simple sequence of chords.
+
+
+ Perfect, you have just encoded a chord in MEI. Now let's continue and add a couple more chords to encode a simple
+ sequence of chords:
+
+
+
+
+ In the editor below, please try to reproduce the chord sequence above with MEI. Notes are enclosed by chord
+ elements. Each chord needs a @dur attribute, and each note needs @pname and
+ @oct attributes.
+
+
diff --git a/_tutorials-BA/103_chords/step-04/103_chords_step-04-desc.html b/_tutorials-BA/103_chords/step-04/103_chords_step-04-desc.html
new file mode 100644
index 00000000..9a2b4ec9
--- /dev/null
+++ b/_tutorials-BA/103_chords/step-04/103_chords_step-04-desc.html
@@ -0,0 +1,24 @@
+
+
+ Step four: encode an extended sequence of chords.
+
+
+ Perfect, you have just encoded a simple chord sequence in MEI. Now let's continue and add some rhythmical variance for a more extended sequence of chords. In fact, we will arrive at an harmonisation of the "Mary had a little lamb" example from the Quickstart tutorial:
+
+
+
+
+ In the editor below, please try to reproduce the chord sequence above with MEI. Notes are enclosed by chord
+ elements. Each chord needs a @dur attribute, and each note needs @pname and
+ @oct attributes.
+
+
+ Keep in mind that the @dur attribute can have values like "1", "2", "4",
+ "8" or "16" to indicate different rhythmical values.
+ For the first chord, you need an additional @dots attribute, where you need to specify
+ the number of dots as an integer – in this case, it's simply a dots="1".
+
+
+ Tip: Once you have laid out the chordal structure, you should be able to copy & paste the block with the three <note> elements.
+
+
diff --git a/_tutorials-BA/104_rests/104_rests.json b/_tutorials-BA/104_rests/104_rests.json
new file mode 100644
index 00000000..5ac5ece5
--- /dev/null
+++ b/_tutorials-BA/104_rests/104_rests.json
@@ -0,0 +1,71 @@
+{
+ "steps": [
+ {
+ "label":"Welcome",
+ "descFile": "104_rests_step-00-desc.html",
+ "xmlFile": "104_rests_step-00.xml",
+ "editorLines":1,
+ "xpaths": [
+ {"rule":"count(//mei:rest) = 1", "renderanyway": false, "hint": "You need a rest element."},
+ {"rule":"count(//mei:rest/@*) = 1 and //mei:rest/@dur", "renderanyway": false, "hint": "You need a @dur attribute."},
+ {"rule":"//mei:rest/@dur = '4'", "renderanyway": true, "hint": "The @dur attribute uses values like '1','2', or '4'. Use the latter for a quarter rest."}
+ ]
+ },
+ {
+ "label":"Different durations",
+ "editorLines":5,
+ "descFile": "104_rests_step-01-desc.html",
+ "xmlFile": "104_rests_step-00.xml",
+ "xpaths": [
+ {"rule":"count(//mei:rest) = 5", "renderanyway": true, "hint":"You need to encode five rest elements."},
+ {"rule":"//mei:rest[1]/@dur and //mei:rest[1]/@dur = '1'", "renderanyway": true},
+ {"rule":"//mei:rest[2]/@dur and //mei:rest[2]/@dur = '2'", "renderanyway": true},
+ {"rule":"//mei:rest[3]/@dur and //mei:rest[3]/@dur = '4' and //mei:rest[3]/@dots and //mei:rest[3]/@dots = '1'", "renderanyway": true},
+ {"rule":"//mei:rest[4]/@dur and //mei:rest[4]/@dur = '8'", "renderanyway": true},
+ {"rule":"//mei:rest[5]/@dur and //mei:rest[5]/@dur = '16'", "renderanyway": true}
+ ]
+ },
+ {
+ "label":"Full-measure rests",
+ "editorLines":1,
+ "descFile": "104_rests_step-02-desc.html",
+ "xmlFile": "104_rests_step-02.xml",
+ "prefillFile": "104_rests_step-02-prefill.xml",
+ "xpaths": [
+ {"rule":"count(//mei:mRest) = 1", "renderanyway": true, "hint":"You need one mRest element."},
+ {"rule":"count(//mei:mRest/@*) = 0", "renderanyway": true,"hint":"The mRest element needs no attributes."},
+ {"rule":"count(//mei:layer/mei:*) = 1","renderanyway":true,"hint":"You must encode an mRest element only."}
+ ]
+ },
+ {
+ "label":"Multi-measure rests",
+ "editorLines":1,
+ "descFile": "104_rests_step-03-desc.html",
+ "xmlFile": "104_rests_step-02.xml",
+ "xpaths": [
+ {"rule":"count(//mei:multiRest) = 1", "renderanyway": true, "hint":"You need one multiRest element."},
+ {"rule":"count(//mei:layer/mei:*) = 1","renderanyway":true,"hint":"You must encode a multiRest element only."},
+ {"rule":"count(//mei:multiRest/@*) = 1 and //mei:multiRest/@num", "renderanyway": true,"hint":"The multiRest element needs one attribute here (@num)."},
+ {"rule":"//mei:multiRest/@num = '15'", "renderanyway": true,"hint":"The multiRest should have a duration of 15 measures"}
+ ]
+ },
+ {
+ "label":"Spaces / Invisible rests",
+ "editorLines":6,
+ "descFile": "104_rests_step-04-desc.html",
+ "xmlFile": "104_rests_step-04.xml",
+ "prefillFile": "104_rests_step-04-prefill.xml",
+ "xpaths": [
+ {"rule":"//mei:space/following-sibling::mei:note", "renderanyway": true, "hint":"space element must precede the note element."},
+ {"rule":"count(//mei:space[@dur = '4']) = 3 or (//mei:space[@dur = '2' and @dots = '1']) or (//mei:space[@dur = '2'] and //mei:space[@dur = '4'])", "renderanyway": true}
+ ]
+ }
+ ],
+ "end":"104_rests_end.html",
+ "resp":[
+ {
+ "name":"Johannes Kepper",
+ "affiliation":"Beethovens Werkstatt | Universität Paderborn"
+ }
+ ]
+}
diff --git a/_tutorials-BA/104_rests/104_rests.md b/_tutorials-BA/104_rests/104_rests.md
new file mode 100644
index 00000000..3a2b8bf5
--- /dev/null
+++ b/_tutorials-BA/104_rests/104_rests.md
@@ -0,0 +1,7 @@
+---
+layout: tutorials
+type: tutorial
+name: "BEGINNERS: Rests"
+fullname: "A short tutorial about rests in MEI"
+data: "104_rests.json"
+---
diff --git a/_tutorials-BA/104_rests/104_rests_end.html b/_tutorials-BA/104_rests/104_rests_end.html
new file mode 100644
index 00000000..4b2d415f
--- /dev/null
+++ b/_tutorials-BA/104_rests/104_rests_end.html
@@ -0,0 +1,29 @@
+
+
Congratulations!
+
+ In this tutorial, you learned how to encode rests with MEI. The elements you've learned are:
+
+ These elements are almost always empty and have no child elements. With the space element, you
+ already learned about a fairly advanced mechanism of aligning multiple voices sharing a staff
+ in MEI. If you're interested in that, you may also want to investigate into the @next and
+ @prev attributes from MEI's
+ att.linking
+ attribute class (available on <note> and other events). That attribute class allows to
+ lay "breadcrumbs" through an MEI file that make it possible to follow voices across multiple layers
+ (and staves, if necessary). This would facilitate analytical use of your MEI file, and is not required in
+ most situations, though.
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/104_rests/step-00/104_rests_step-00-desc.html b/_tutorials-BA/104_rests/step-00/104_rests_step-00-desc.html
new file mode 100644
index 00000000..1ea83c1d
--- /dev/null
+++ b/_tutorials-BA/104_rests/step-00/104_rests_step-00-desc.html
@@ -0,0 +1,16 @@
+
+
+ In this tutorial, you will learn how to encode different types of rests from the Common Music Notation repertoire using MEI.
+
+ According to the MEI Specification,
+ a rest is "a non-sounding event found in the source being transcribed". Encoding that is simple:
+ Just use a <rest> element, with a @dur attribute.
+
+
+ Please encode a quarter rest.
+
+
diff --git a/_tutorials-BA/104_rests/step-01/104_rests_step-01-desc.html b/_tutorials-BA/104_rests/step-01/104_rests_step-01-desc.html
new file mode 100644
index 00000000..fcf2908e
--- /dev/null
+++ b/_tutorials-BA/104_rests/step-01/104_rests_step-01-desc.html
@@ -0,0 +1,14 @@
+
+
+ Congratulations, you just encoded your first rest. The next one will be easy:
+
+ Encode a sequence of five rests:
+
+
+
+ For the third rest, you need an additional @dots attribute, where you need to specify
+ the number of dots as an integer – in this case, it's simply a dots="1". Keep in mind that the
+ @dur attribute can have values like "1", "2", "4",
+ "8" or "16".
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/104_rests/step-02/104_rests_step-02-desc.html b/_tutorials-BA/104_rests/step-02/104_rests_step-02-desc.html
new file mode 100644
index 00000000..25b8603d
--- /dev/null
+++ b/_tutorials-BA/104_rests/step-02/104_rests_step-02-desc.html
@@ -0,0 +1,16 @@
+
+
+ Very often, a rest is supposed to fill up a complete measure, independent of the meter.
+ Of course it is possible to use regular <rest> elements with the proper
+ duration(s) for that – in case of a meter of 4/4, this would be just a
+ <rest dur="1"/>. However, in other meters this may require more markup.
+ For that reason, MEI has a special element called <mRest/> – a
+ measure rest. This element needs no @dur attribute (even though it's
+ technically allowed to facilitate analytical processing), and will always fill up a
+ complete measure, independent of the meter. Therefore, you should not combine it with
+ other events in the same measure.
+
+
+ Please turn the whole rest (which does not fit the meter) into an <mRest/>.
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/104_rests/step-03/104_rests_step-03-desc.html b/_tutorials-BA/104_rests/step-03/104_rests_step-03-desc.html
new file mode 100644
index 00000000..29dc0d69
--- /dev/null
+++ b/_tutorials-BA/104_rests/step-03/104_rests_step-03-desc.html
@@ -0,0 +1,14 @@
+
+
+ Mostly in music organized in parts, there are frequently rests that last for more than one measure.
+
+
+
+ In MEI, these rests are encoded using the special element <multiRest/>. It uses plain
+ integers in the @num attribute to specify the number of measures which the performer of that
+ part is supposed to rest.
+
+
+ Please encode a <multiRest/> lasting for 15 measures.
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/104_rests/step-04/104_rests_step-04-desc.html b/_tutorials-BA/104_rests/step-04/104_rests_step-04-desc.html
new file mode 100644
index 00000000..b4e3c5e5
--- /dev/null
+++ b/_tutorials-BA/104_rests/step-04/104_rests_step-04-desc.html
@@ -0,0 +1,40 @@
+
+
+ When music is laid out with multiple instruments / voices sharing a staff, it is sometimes
+ necessary to "push" events like notes to a later position in the measure, without saying they
+ are resting. This is usually the case when the document that's supposed to be encoded
+ switches between chord-based notation and separated stems within a measure (cf. figure below). As MEI uses the
+ <layer> element to lay out
+ multiple instruments, and in these situations an instrument switches between those layers
+ mid-measure, the "gaps" in those measures need to be filled. This is what the
+ <space> element is for.
+
+
+
+ Of course, a space isn't really a rest. However, (invisible) rests are often (ab)used for these
+ purposes in other encoding formats or scorewriters. The benefit of MEI's <space> element is that it carries no
+ semantic meaning – it just pushes other events around. This makes it much easier to actually process
+ an encoding and extract individual voices for it, as no non-existent information-carrying element is
+ falsely introduced just for better coordination.
+
+
+ However, you can apply a certain duration to the <space> element by using the @dur
+ attribute. You can even use @dots to extend that duration by half its value. The duration you apply to
+ <space> is the number of beats that the events, like a <note>, following the
+ <space> are shifted to the right.
+
+
+ In the editor below, you see a prefilled encoding of a note G4 (positioned at the first beat in the second layer).
+ Please push this note to the end of the measure, so that it sits on the final beat under the D5, as in the image
+ above. To do so, use the <space> element and apply an appropriate duration (it must be 3 beats
+ altogether). In fact, there are multiple ways to encode it:
+
+
with three <space>'s using the same value for @dur,
+
with two <space> elements using only @dur, but with two different values,
+
or even with only one <space> element, using@dur and @dots.
+
+
+ You may play a little bit with the attribute values to see how they influence the rendering. Do you find all
+ three possible solutions?
+
+ This is an advanced tutorial that intends to explain the internal structures of MEI. Using those structures, it is possible to restrict
+ MEI to the specific requirements and perspectives of any given use case, which is generally considered as good practice. Only with such
+ a restricted (generally referred to as "customized") version of MEI, one may enforce the editorial principles of a given project, which
+ helps to technically ensure data quality. Even though such validation hardly stops semantic errors (the encoding of wrong pitches, for
+ instance), it ensures that only such markup is used that the project's workflow is tailored for, and no misinterpretations can arise from
+ unexpected markup.
+
+
+ This tutorial will introduce the basic concepts of the ODD language, which is used to define MEI. In a second tutorial, we will introduce
+ workflows and tools that help to create individual customizations. It is highly recommended to first familiarize yourself with the
+ underlying structures in this tutorial.
+
+
+ Admittedly, this is one of the most advanced topics around MEI, and it certainly takes some time to familiarize yourself with the use of ODD.
+ However, the wide MEI Community is more than happy to answer questions,
+ and the same is certainly true for the MEI Technical
+ Team. Just take your time with this tutorial, and also have a closer look at the
+ corresponding MEI Guidelines chapter.
+ Eventually, you will become proficient in the discipline of using DH standards like MEI – just continue from here on :-)
+
+
diff --git a/_tutorials-BA/180_understanding-odd/180_understanding_odd-02.html b/_tutorials-BA/180_understanding-odd/180_understanding_odd-02.html
new file mode 100644
index 00000000..7b8a5ed6
--- /dev/null
+++ b/_tutorials-BA/180_understanding-odd/180_understanding_odd-02.html
@@ -0,0 +1,25 @@
+
+
+ ODD, an acronym for One Document Does-it-all, is a part of the
+ TEI standard,
+ and is also used to define TEI itself.
+
+
+ ODD uses a set of special elements in the TEI namespace to
+ describe XML-based data formats. Besides core TEI, it is used for TEI-based formats like
+ EpiDoc, but also for technically independent
+ formats like MEI. In 2016, the TEI came up with a version of ODD called
+ Pure ODD. As of Summer 2020,
+ MEI however continues to use the older flavor of ODD, as the new version brings no pertinent benefits for MEI, but would
+ result in significant maintenance work for various MEI-related tools and workflows.
+
+
+ The main difference to Pure ODD is that the older version used by MEI uses elements from the
+ RelaxNG namespace. Eventually, ODD files are usually compiled
+ to a RelaxNG (or XSD) schema anyway, as there is literally no software support for direct validation against ODD. However,
+ this recourse to RelaxNG within ODD adds an additional dependency into the TEI workflow, and thus reduces the technical freedom
+ for defining TEI and / or ODD to some (minor?) degree. As MEI is already defined in a format that is out of (direct) control
+ of the MEI community, and needs to deal with multiple XML namespaces anyway, the argument to have everything defined consistently
+ in Pure ODD is less striking, and accordingly hasn't been followed so far.
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/180_understanding-odd/180_understanding_odd-03.html b/_tutorials-BA/180_understanding-odd/180_understanding_odd-03.html
new file mode 100644
index 00000000..19d5fe5b
--- /dev/null
+++ b/_tutorials-BA/180_understanding-odd/180_understanding_odd-03.html
@@ -0,0 +1,26 @@
+
+
+ Despite it's name, the setup for working with ODD usually requires at least twological files (though these may spread
+ across many more files in the file system, as shown in the following step of this tutorial). The first of these files is the
+ so-called source: It holds the full specification of the format, in this case MEI. In our repository, it is located in the
+ mei-source.xml file.
+ In addition to that file, a separate customization is required to specify which parts of the specification are to be used
+ in a given context. The whole purpose of ODD is to allow flexible customizations of the schema. MEI provides a set of
+ pre-defined profiles,
+ which are nothing but customizations of the MEI schema.
+
+
+ In order to use MEI (or any other ODD-based format), the customization file is used to
+ control how the source file shall be compiled. There are several target formats for that
+ compilation, which is explained elsewhere. The most
+ common target is a RelaxNG file, which contains
+ both RelaxNG hierarchies and additional Schematron rules as defined in the ODD, and can be used for
+ validation against both types of schema. All other possible output formats are not commonly used for
+ MEI. (Side note: we'll come back to a brief explanation of Schematron later in this tutorial.)
+
+
+ While this tutorial is focussed on explaining the basic principles of the ODD structures as found in the MEI sources, a separate tutorial
+ on ODD will explain how to customize MEI to specific needs. The following steps will introduce the mechanisms of the main ODD structures in MEI:
+ modules, elements, models, attributes, datatypes and macros. Let's continue in order to start with a closer look at modules…
+
+
diff --git a/_tutorials-BA/180_understanding-odd/180_understanding_odd-04.html b/_tutorials-BA/180_understanding-odd/180_understanding_odd-04.html
new file mode 100644
index 00000000..ebe81d7c
--- /dev/null
+++ b/_tutorials-BA/180_understanding-odd/180_understanding_odd-04.html
@@ -0,0 +1,44 @@
+
+
+ The highest-level conceptual structure in ODD are modules. Modules allow to divide the schema
+ into different areas, each of which defining a clearly delimited aspect. Until 2019, the structure of the
+ MEI Guidelines followed the ODD modules, but this setup has been superseded by a more instructional division.
+ Right now, the modules show up in the MEI Guidelines at the top of the definitions of elements, attributes etc.:
+
+
+
+
+
+ This is just an easy reference to the modules. If planning to work on the MEI ODD, however, it is more important
+ to know that the MEI source code is splitted up following the modules. The file
+ mei-source.xml
+ acts as starting point into the MEI specification. The
+ <schemaSpec>
+ element in line 83
+ defines a new schema with the MEI namespace (@ns="http://www.music-encoding.org/ns/mei"). It then has a number of
+ XInclude child elements. XInclude is used to split up one larger logical XML file into smaller, more manageable files. Here,
+ every MEI module is stored in a separate file in the
+ modules subfolder.
+
+
+ The MEI modules are built around different topics. There are modules which focus on specific musical repertoires
+ (CMN,
+ Mensural,
+ Neumes, or
+ String Tablature),
+ but also modules for specific perspectives on music
+ (visual,
+ gestural,
+ analytical),
+ technologies (
+ MIDI) or use cases
+ (facsimiles,
+ performances,
+ editorial use).
+ The scope of each of these modules is described in the MEI Guidelines.
+
+
+ Besides the better maintainability of the MEI source code due to smaller file sizes, the splitting mainly allows to "turn off"
+ larger parts (-> modules) of the MEI schema very easily.
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/180_understanding-odd/180_understanding_odd-05.html b/_tutorials-BA/180_understanding-odd/180_understanding_odd-05.html
new file mode 100644
index 00000000..c4e013a8
--- /dev/null
+++ b/_tutorials-BA/180_understanding-odd/180_understanding_odd-05.html
@@ -0,0 +1,99 @@
+
+
+ The most obvious building blocks for the MEI specification are the definitions of elements. They are done using the TEI's
+ <elementSpec> element.
+ Let's have a look at MEI's <castItem>
+ element:
+
+
<elementSpec ident="castItem" module="MEI.shared">
+ <desc>Contains a single entry within a cast list, describing either a single role or a list of non-speaking roles.</desc>
+ <classes>
+ <memberOf key="att.common"/>
+ <memberOf key="att.bibl"/>
+ <memberOf key="att.facsimile"/>
+ <memberOf key="att.lang"/>
+ </classes>
+ <content>
+ <rng:oneOrMore>
+ <rng:choice>
+ <rng:text/>
+ <rng:ref name="role" />
+ <rng:ref name="roleDesc" />
+ <rng:ref name="actor" />
+ <rng:ref name="perfRes" />
+ </rng:choice>
+ </rng:oneOrMore>
+ </content>
+ <remarks>
+ <p part="N">This element is modelled on an element in the Text Encoding Initiative (TEI) standard.</p>
+ </remarks>
+</elementSpec>
+
+
+
+ The <castItem> element has a very short specification, which still provides a lot of information
+ about it. First, the name of the element is specified in the @ident attribute on the
+ <elementSpec> element. In addition, the module it belongs to is specified with the @module
+ attribute. The MEI.shared module used in this case serves as a fallback for many generic elements which do
+ not fit well into other modules or which are indispensable for using MEI.
+
+
+ We then see a <desc> element that gives a very brief explanation of the purpose and scope of the
+ element in question. This information is often used in software as a tooltip to guide an encoder to using the proper
+ elements. A speaking description is therefore extremely important.
+
+
+ The next piece of information is provided with the <classes> element, which specifies to
+ which classes the element belongs. We will cover this later in greater detail, but to give you a first
+ understanding: This is used to define which attributes are available on the element, and where it may
+ be used inside an MEI file.
+
+
+ We now see the <content> element, which defines what can go inside our element.
+ Here, the version of ODD used by MEI switches to the RelaxNG namespace (http://relaxng.org/ns/structure/1.0),
+ as indicated by the rng: prefix to the element names. The next levels of markup can be understood quite
+ intuitively from the elements' names: The content can be one or more of a choice of either
+ textual content, or the elements
+ <role>,
+ <roleDesc>,
+ <actor>, or
+ <perfRes>.
+ The nesting of <rng:oneOrMore> and <rng:choice> makes it clear that there is no
+ particular order for those child elements, and that they may be freely intermixed with textual content.
+
+
+ What we see here are direct references (<rng:ref>) to specific elements, as identified by their
+ respective @ident attributes. In the following step of this tutorial, we will see a more flexible
+ approach using so-called model classes. Both approaches can be mixed as needed.
+
+
+ The only other information provided by this <elementSpec> are <remarks>. Whereas the
+ <desc> element provides only a very brief explanation of an element (typically about one sentence),
+ <remarks> often provide additional explanation on the use of an element, or, as in this case, that
+ it is derived from an existing element in a different format.
+
+
+ In addition to the things seen here on <castItem>, ODD offers two more things than can be specified
+ on elements. Sometimes, it is easier or more appropriate to specify attributes directly on an element, instead of
+ using attribute classes. An example for that can be found at the
+ <title> element, which
+ has both @level and @type defined locally using the
+ <attList> element inside
+ <elementSpec>.
+
+
+ The other type of information missing from <castItem> is Schematron rules, which
+ may be provided using
+ <constraintSpec>
+ elements. While Schematron is an integral part of MEI and helps to enforce certain context-dependent assertions
+ in MEI instances, a full documentation would be well beyond the scope of this tutorial. There are other tutorials available online (see
+ here or
+ here), and of course
+ one may use existing Schematron rules in MEI to better understand how it is applied. A good starting point for that is surely the
+ <staffDef> element,
+ which is controlled by a considerable number of Schematron rules.
+
+
+ Let's move on to the class concept of ODD, which is crucial for the flexibility and customizability of MEI.
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/180_understanding-odd/180_understanding_odd-06.html b/_tutorials-BA/180_understanding-odd/180_understanding_odd-06.html
new file mode 100644
index 00000000..0000ca35
--- /dev/null
+++ b/_tutorials-BA/180_understanding-odd/180_understanding_odd-06.html
@@ -0,0 +1,132 @@
+
+
+ As we've seen, ODD allows to specify which exact child elements are allowed inside a given
+ element. This allows for a very fine-grained control of the MEI hierarchy, but it comes at
+ the cost of very verbose listings of what each element may contain. This is neither particularly
+ maintainable nor easy to follow: Some elements in MEI may contain dozens of other elements,
+ and comparing two such elements is rather cumbersome.
+
+
+ Among others, the
+ <castItem>
+ element from the last step of this tutorial had a child element
+ <role>. The documentation
+ for <role> lists a total of 54 child elements, plus textual content:
+
+
+
+
+
+ Looking at the <elementSpec> there is no such listing, however:
+
+
<elementSpec ident="role" module="MEI.shared">
+ <desc>Name of a dramatic role, as given in a cast list.</desc>
+ <classes>
+ <memberOf key="att.common"/>
+ <memberOf key="att.facsimile"/>
+ <memberOf key="att.lang"/>
+ </classes>
+ <content>
+ <rng:zeroOrMore>
+ <rng:choice>
+ <rng:text/>
+ <rng:ref name="model.textPhraseLike.limited" />
+ </rng:choice>
+ </rng:zeroOrMore>
+ </content>
+ <remarks>
+ <p part="N">This element is modelled on an element in the Text Encoding Initiative (TEI) standard.</p>
+ </remarks>
+</elementSpec>
+
+ Instead of the 54 elements from the screenshot above, only one <rng:ref> is given, pointing to something
+ named model.textPhraseLike.limited. This is a so-called model class. Model classes are intended to
+ serve as placeholders for groups of elements. The model class itself does not know which elements are part of it:
+
+
<classSpec ident="model.textPhraseLike.limited" module="MEI.shared" type="model">
+ <desc>Groups textual elements that occur at the level of individual words or phrases. This class is equivalent to the model.textPhraseLike class without the pb element.</desc>
+ <classes>
+ <memberOf key="model.rdgPart.text"/>
+ <memberOf key="model.editTransPart.text"/>
+ <memberOf key="model.textPhraseLike"/>
+ </classes>
+</classSpec>
+
+ A model class is encoded with a
+ <classSpec> element,
+ which has the @type="model" attribute. Like elements, it's uniquely identified using the @ident
+ attribute. It is assigned to one of the MEI modules with the @module attribute.
+ MEI follows the convention that all model class names are prefixed with the string "model.". They also always have
+ a <desc> with a brief explanation of the purpose of the group. Let's skip the <memberOf> elements on
+ <classSpec> from the example above for a moment, and let's see how those 54 elements we've seen above are bound to
+ model.textPhraseLike.limited.
+
+
+ If we go to the MEI Guidelines for
+ model.textPhraseLike.limited,
+ we see that six elements are direct "members" of this model class: <dedicatee>, <dimensions>,
+ <extent>, <seg>, <symbol>, and <term>. Let's have a look into <dedicatee>:
+
+
<elementSpec ident="dedicatee" module="MEI.shared">
+ <desc>Entity to whom a creative work is formally offered.</desc>
+ <classes>
+ <-- other memberShips removed for brevity -->
+ <memberOf key="model.textPhraseLike.limited"/>
+ </classes>
+ <content>
+ <rng:zeroOrMore>
+ <rng:choice>
+ <rng:text/>
+ <rng:ref name="model.textPhraseLike.limited" />
+ </rng:choice>
+ </rng:zeroOrMore>
+ </content>
+ <-- constraintSpec removed for brevity-->
+</elementSpec>
+
+ The element has a <memberOf> element, which uses its @key attribute to reference the
+ model.textPhraseLike.limited model class. So, an element claims membership in a given model class, and it will be automatically allowed
+ everywhere this model class is allowed within the <content> of an element. As a side note: this means that <dedicatee> may be
+ self-nested (one dedicatee element may contain another dedicatee as child element), which is rather a side effect of the class system than an
+ intended feature of MEI…
+
+
+ However, in regular MEI only six elements are direct members of model.textPhraseLike.limited, but we saw that by referencing this model
+ class, a total of 54 elements are added as allowed content (= child elements). Where do the remaining 48 elements come from? Admittedly, the current
+ presentation of the Guidelines doesn't present well where those additional elements come from. The answer are
+ nested model classes. One model class can be a member of another model class, as we've seen in the <classSpec>
+ above. Let's go back to the allowed children of the <role> element, but in the by class perspective:
+
+
+
+
+
+ We see the six direct children listed, but also that <fig> is listed under the model.figureLike label, and <catchwords>
+ and <fingerprint> are coming from model.msInline.
+ This listing continues and explains the origin of all
+ 54 elements. If we have a look at model.figureLike, we see that this class has a <memberOf>, pointing to model.textPhraseLike.limited:
+
+
<classSpec ident="model.figureLike" module="MEI.figtable" type="model">
+ <desc>Groups elements representing or containing graphic information such as an illustration or figure.</desc>
+ <classes>
+ <memberOf key="model.textPhraseLike.limited"/>
+ </classes>
+</classSpec>
+
+ So, model.figureLike is a member of model.textPhraseLike.limited, which means that wherever model.textPhraseLike.limited
+ is allowed as child content, model.figureLike (and all the elements which are members of it) is also allowed. The deepest nesting
+ of classes within model.textPhraseLike.limited is actually three: model.nameLike.geogName is a member of model.nameLike.place,
+ which is a member of model.nameLike, which is a member of model.textPhraseLike.limited. All elements which are members of any of those
+ classes will be allowed as children of any element which has a <rng:ref name="model.textPhraseLike.limited" /> in its <content>.
+
+
+ As you can see from the names in that class hierarchy above, more specific classes are members of more generic classes. When trying to identify the
+ set of elements that should be allowed inside a given (new) element, one may purposely pick a class that adds some very specific elements, or that
+ brings a very wide slate of elements. This system of model classes makes it very easy to be very selective on the allowed contents of elements. It
+ also makes it very easy to introduce new elements into MEI: By subscribing to existing model classes, those elements will be automatically included
+ in the schema in all the places those model classes are allowed already.
+
+
+ Now let's move on to attributes, which are handled in a very similar manner.
+
+
diff --git a/_tutorials-BA/180_understanding-odd/180_understanding_odd-07.html b/_tutorials-BA/180_understanding-odd/180_understanding_odd-07.html
new file mode 100644
index 00000000..bc01957a
--- /dev/null
+++ b/_tutorials-BA/180_understanding-odd/180_understanding_odd-07.html
@@ -0,0 +1,131 @@
+
+
+ As we've seen on the previous step, a lot of the MEI hierarchy is established through the use of model classes. A very similar
+ mechanism is used by ODD to make attributes available on multiple elements. But before dealing with attribute classes, let's have
+ a brief look on how an attribute is actually defined in ODD. The @xml:id attribute is available on every MEI element, and
+ is defined with the following specs:
+
+
<attDef ident="xml:id" usage="opt">
+ <desc>Regularizes the naming of an element and thus facilitates building links between it and other resources. Each id attribute within a document must have a unique value.</desc>
+ <datatype maxOccurs="1" minOccurs="1">
+ <rng:data type="ID"/>
+ </datatype>
+ </attDef>
+
+ Attributes are specified using the <attDef>
+ element, and follow some conventions we've already seen on elements and model classes: Their name is provided in the @ident attribute,
+ and they have a <desc> element with a brief description. What is new is the @usage attribute, which specifies
+ when to use the attribute specified. The value here, "opt", is used for optional attributes – @xml:id can be used on all MEI
+ elements, but doesn't have to be used. Other allowed values for @usage are "req" (required) and "rec" (recommended when
+ applicable).
+
+
+ Now let's have a look for these <attDef> elements are located. Even though that's not really the preferred solution, sometimes
+ attributes are defined at the element where they need to be used, as with the @type attribute on
+ <meiHead>:
+
+
<elementSpec ident="meiHead" module="MEI.header">
+ <desc>(MEI header) – Supplies the descriptive and declarative metadata prefixed to every
+ MEI-conformant text.</desc>
+ <classes>
+ <!-- memberOf elements skipped for brevity -->
+ </classes>
+ <content>
+ <!-- contents skipped for brevity -->
+ </content>
+ <!-- constraintSpecs skipped for brevity -->
+ <attList>
+ <attDef ident="type" usage="opt">
+ <desc>Specifies the kind of document to which the header is attached, for example whether it
+ is a corpus or individual text.</desc>
+ <valList type="closed">
+ <valItem ident="music">
+ <desc>Header is attached to a music document.</desc>
+ </valItem>
+ <valItem ident="corpus">
+ <desc>Header is attached to a corpus.</desc>
+ </valItem>
+ <valItem ident="independent">
+ <desc>Header is independent; i.e., not attached to either a music or a corpus
+ document.</desc>
+ </valItem>
+ </valList>
+ </attDef>
+ </attList>
+ <!-- remarks skipped for brevity -->
+</elementSpec>
+
+ As we can see, attributes are just contained in an <attList> child inside the <elementSpec>. However, in most cases,
+ an attribute is supposed to be available on more than one element. The @xml:id attribute introduced above is available on every MEI
+ element, so it would have to be defined several hundred times – again, that's neither maintainable nor efficient. Instead, ODD again utilizes
+ a class system, this time for attribute classes. Let's have a look how @xml:id is actually distributed into
+ MEI using the att.id attribute class:
+
+
<classSpec ident="att.id" module="MEI.shared" type="atts">
+ <desc>Attributes that uniquely identify an element.</desc>
+ <attList org="group">
+ <attDef ident="xml:id" usage="opt">
+ <!-- skipping this, as it is the very same as in the example above -->
+ </attDef>
+ </attList>
+</classSpec>
+
+ We've already seen the <attDef>, and there is no difference between attributes defined within an element or within an attribute class.
+ But we've also already seen the <classSpec> element
+ on model classes. The only difference is that attribute classes use the @type="atts" attribute, and while the names of
+ model classes already start with "model.", attribute classes in MEI will always have a name starting with "att.".
+
+
+ Earlier in this tutorial, we saw the definition of the <role>
+ element. Let's have a look on it again, skipping some parts of it:
+
+
<elementSpec ident="role" module="MEI.shared">
+ <desc>Name of a dramatic role, as given in a cast list.</desc>
+ <classes>
+ <memberOf key="att.common"/>
+ <memberOf key="att.facsimile"/>
+ <memberOf key="att.lang"/>
+ </classes>
+ <!-- skipping content and remarks here -->
+</elementSpec>
+
+ According to this, <role> is a <memberOf> the attribute classes att.common, att.facsimile, and
+ att.lang, but not att.id. Yet still, the documentation of <role> states that @xml:id is available. The answer
+ to this is again the use of nested classes. <role> subscribes to the att.common attribute class and gets all attributes
+ from that class (which are none, actually). att.common in turn subscribes (= is a member of) to the att.basic attribute class (among
+ other classes), which brings in the @xml:base attribute, and which subscribes to the att.id attribute class, which eventually brings in
+ @xml:id. To see that mechanism in action, let's have a brief look at att.common:
+
+ Again, it is through the use of a <memberOf element with the proper @key how membership in different classes is achieved in
+ MEI, so this mechanism should be familiar already. And just like with model classes, attribute classes are used from rather generic
+ classes to very specific sets of well-aligned attributes. By subscribing to the right attribute class(es), an element may thus get just the right set of
+ attributes, and it becomes possible to selectively add or remove attributes to new or existing elements by modifying these memberships.
+
+
+ In specs for att.common above reveal another attribute class att.typed which provides an attribute
+ @type. Obviously, this hasn't been used on <meiHead>, as seen above. The reason is that the attribute class
+ provides a @type attribute which has only a very generic description: Designation which characterizes the element
+ in some sense, using any convenient classification scheme or typology that employs single-token labels.
+ Compared to that, the @type on <meiHead> had a very strict definition. In general, MEI seeks to avoid
+ using the same attribute name with multiple definitions, but that's not always possible, and at least doesn't cause
+ technical confusion. With the "by class" perspective on attributes (see the
+ <meiHead> specs),
+ its possible to easily trace where any allowed attribute comes from.
+
+
+ The only major part left to understand ODD as it is used to define MEI are data types, which will be introduced in the
+ following step of this tutorial.
+
+
diff --git a/_tutorials-BA/180_understanding-odd/180_understanding_odd-08.html b/_tutorials-BA/180_understanding-odd/180_understanding_odd-08.html
new file mode 100644
index 00000000..882a604b
--- /dev/null
+++ b/_tutorials-BA/180_understanding-odd/180_understanding_odd-08.html
@@ -0,0 +1,159 @@
+
+
+ Most data types in ODD are following common, well-established concepts: There are integers, boolean values, strings, and
+ so on. Let's have a closer look at some of them. The @n attribute is defined within the
+ att.nInteger attribute
+ class:
+
+
<attDef ident="n" usage="opt">
+ <desc>Provides a numeric designation that indicates an element's position in a sequence of similar elements. Its value must be a non-negative integer.</desc>
+ <datatype maxOccurs="1" minOccurs="1">
+ <rng:data type="nonNegativeInteger"/>
+ </datatype>
+</attDef>
+
+ This is using a <data> element from the rng: namespace, where @type uses a value defined within
+ RelaxNG. The @maxOccurs and @minOccurs attributes define how often a value of this type may be given. An
+ example for other values can be found for the @staff attribute defined in att.staffIdent. This attribute
+ is used to associate
+ controlevents
+ with one or more staves, and may hold one or more integers. It uses
+ the following markup to achieve this:
+
+ In other cases, MEI defines its own datatypes. This is done with a
+ <macroSpec> element.
+ Let's have a look at the
+ data.BARRENDITION
+ data type, which is used to define the appearance of barlines:
+
+ Again, the @ident and @module attributes are used as we've seen elsewhere before, as is the
+ <desc> child element. What is important is the @type attribute with a value of "dt" (data type).
+ By convention, all data type names are prefixed with "data.", and the following name is given in all capitals.
+ We then have a value list, which in this case is closed. This means that all possible values are enumerated here. In
+ other cases, a @type of "semi" indicates a semi-open list. Such a list provides recommendations,
+ but allows a user to come up with custom values when none of the suggestions match the current situation. This typically provides
+ a good balance between ensuring consistency and allowing on-demand extensibility of the schema.
+
+
+ Like with model and attribute classes, data types may be nested. One example for this is the
+ data.NOTEHEADMODIFIER
+ data type:
+
+
<macroSpec ident="data.NOTEHEADMODIFIER" module="MEI" type="dt">
+ <desc>Captures any notehead "modifiers"; that is, symbols added to the notehead, such as slashes, lines, text, and enclosures, etc.</desc>
+ <content>
+ <rng:choice>
+ <rng:ref name="data.NOTEHEADMODIFIER.list" />
+ <rng:ref name="data.NOTEHEADMODIFIER.pat" />
+ </rng:choice>
+ </content>
+</macroSpec>
+
+ This means that an attribute that uses the data.NOTEHEADMODIFIER data type will accept values that will follow
+ the rules of either the data.NOTEHEADMODIFIER.list or data.NOTEHEADMODIFIER.pat data types.
+
+
+ One last data type that we'd like to introduce is data.COLORVALUES, which is used by data.COLOR, which
+ in turn is used to control the values of attributes like @color (through
+ att.color)
+ or @beam.color (through
+ att.beaming.vis).
+ It uses a set of regular expressions to control different color encoding mechanisms:
+
+ The <rng:choice> around the different <rng:data> elements states that a value of
+ the @color attribute must follow either one of the contained regex patterns.
+ Explaining the semantics of regular expressions is clearly out of scope for this tutorial – in essence, it
+ is a way to describe a pattern for a string, and can be used to check wether that string matches the pattern or not.
+ A nice starting point into regular expressions is the Regex Crossword, available from
+ https://regexcrossword.com/.
+
+
+ There are many other data types that can be used, but as nesting typically isn't as deep as with model or
+ attribute classes, data types are often considered to be more accessible when getting into ODD – there is
+ surely less to learn. So let's move on to Macros.
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/180_understanding-odd/180_understanding_odd-09.html b/_tutorials-BA/180_understanding-odd/180_understanding_odd-09.html
new file mode 100644
index 00000000..88f3909e
--- /dev/null
+++ b/_tutorials-BA/180_understanding-odd/180_understanding_odd-09.html
@@ -0,0 +1,58 @@
+
+
+ Macros are the last part of ODD that is needed to fully understand the specifications of MEI, and they are clearly the
+ least important aspect. Macros are placeholders for elements which can be added to the <content>
+ of an element in one go. The most-used macro is probably macro.struc-unstrucContent, which is defined as follows:
+
+ Macros again use the <macroSpec>
+ element, but this time with a @type with value "pe". The names, which are again stored in @ident,
+ are prefixed with a "macro.", and of course we have a <desc> again. The main difference to model
+ classes is that macros do not substitute for elements alone, but also for more complex rules about combinations
+ of elements. Here, macro.struc-unstrucContent provides a good example. It forces the user to decide between
+ a structured encoding model (using a dedicated <head> element, followed by a series of paragraphs), or an
+ unstructured model (where textual content is directly inserted and may be marked up with a variety of elements). It can be used
+ inside elements like <watermark>, and is helpful to avoid having to redefine the same combination of elements in
+ numerous places.
+
+
<elementSpec ident="watermark" module="MEI.header">
+ <desc>Contains a description of a watermark or similar device.</desc>
+ <classes>
+ <!-- memberships skipped for brevity -->
+ </classes>
+ <content>
+ <rng:ref name="macro.struc-unstrucContent" />
+ </content>
+ <!-- remarks skipped for brevity -->
+</elementSpec>
+
+ In essence, the <rng:ref> inside the <elementSpec> is just replaced with the child elements of
+ the <macroSpec>'s <content>, so that it's possible to combine a macro with other contents. Macros
+ therefore serve as predefined, re-usable spec blocks.
+
+
+ Like I mentioned earlier, macros are not the most important aspect of ODD from an MEI perspective, and so you should have
+ been able to get all that's necessary already. That means you're done with this final step – let's continue for some closing remarks…
+
+
diff --git a/_tutorials-BA/180_understanding-odd/180_understanding_odd-end.html b/_tutorials-BA/180_understanding-odd/180_understanding_odd-end.html
new file mode 100644
index 00000000..2f359747
--- /dev/null
+++ b/_tutorials-BA/180_understanding-odd/180_understanding_odd-end.html
@@ -0,0 +1,17 @@
+
+
+ Congratulations! You've successfully made your way through this introduction into ODD from an MEI
+ perspective. You should now know and understand all the building blocks of the MEI specification. Admittedly, it has
+ been a tough ride, and you may have to re-read it a couple of times to really familiarize yourself. What is important
+ to keep in mind is that the version of ODD MEI currently uses is slightly outdated, and may not be perfectly aligned
+ with the TEI documentation anymore. Nevertheless, all MEI tools and workflows are operating properly with this version,
+ so from an MEI perspective, there is nothing wrong with the current situation.
+
+
+ The next step from here on is to learn how to write actual MEI customizations using ODD. There is
+ a separate tutorial for this (or will be soon…), which will go into the details of that process. Such customizations
+ will use some additional concepts on top of what you've learned here, but it is crucial to fully understand the
+ underlying concepts first. As soon as you feel like you've understood ODD so far, this extra level shouldn't worry
+ you anymore. And with proper customizations, you will be able to make expert use of MEI for your needs :)
+
+ This is an advanced tutorial that introduces how to customize MEI for project-specific needs. It assumes a solid understanding of the
+ internal ODD structures of MEI, as described in the Understanding ODD
+ tutorial. If you're not familiar with <elementSpec>
+ elements, model classes and attribute classes, it is probably better to go back to that tutorial first.
+
+
+ Now let's start with our current tutorial. The purpose of customizations is to restrict the MEI schema to just those
+ parts of the framework which are relevant for a given task or project. It is also possible to extend MEI using the same
+ mechanisms described here, but this is left to yet another tutorial. For now, the focus is on subsetting MEI, though, as files
+ validated against such a customized version of MEI will also validate against the
+ MEI All customization, which resembles the full
+ MEI framework. This ensures a substantial level of compatibility with existing tools and documentation. In general, extensions to MEI
+ should be made only when absolutely necessary, and it's usually a good idea in such situations to consult with the
+ MEI Community to verify that no other
+ solution exists already.
+
+
+ In this tutorial, we will first learn how to use the MEI ProfileDrafter,
+ which provides a graphical user interface for generating basic restricting customizations. It is part of the
+ MEI Garage, and while being somewhat limited, it
+ definitely helps to better understand the concepts of MEI Customizations. Next, we will examine the output
+ of the MEI ProfileDrafter and see how to generate a RelaxNG file for validation purposes from that. Finally, we will introduce
+ some more advanced customization options, which are beyond the scope of the MEI ProfileDrafter. You may want to use a XML Editor
+ application at some point to follow along, but we'll be using web services for all processing, so it really doesn't matter which
+ editor you choose – any is fine. With that out of the way, let's get started!
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/181_customizing_MEI/181_customizing_mei-02.html b/_tutorials-BA/181_customizing_MEI/181_customizing_mei-02.html
new file mode 100644
index 00000000..1c6e2fee
--- /dev/null
+++ b/_tutorials-BA/181_customizing_MEI/181_customizing_mei-02.html
@@ -0,0 +1,54 @@
+
+
+ For the following steps, you should open the
+ MEI ProfileDrafter
+ in a separate browser window (or tab) to follow along with these instructions.
+
+
+
+ When you open the ProfileDrafter, you will see a list of all MEI Modules in the center column. For each,
+ the number of elements and attribute classes in that module is given. Individual modules can be turned off
+ by unchecking the checkbox left to their name. Please disallow some MEI modules by unchecking them.
+
+
+ It is fairly simple to (de-)select MEI modules, isn't it? However, by using this checkbox only, you get very little
+ feedback on the consequences of your choices – the user interface isn't really telling you what you're taking out of
+ the schema with these selections. However, each module box also has a customize-button in its top-right corner.
+ When clicking this button, the list of modules in the center column is replaced by a list of all elements and attribute classes
+ that are part of the current module. Please note that this is only possible for modules that you haven't excluded for the schema.
+
+
+ If you click to customize the MEI.cmnOrnaments module, you will see a list with
+ the <mordent>, <trill>, and <turn> elements, and the att.mordent.log, att.ornamentAccid,
+ att.ornamPresent, att.trill.log, and att.turn.log attribute classes. Again, you can unselect any
+ of those, depending on your specific needs. While on the last screen, you've been able to turn off modules in full, here you
+ can make selective choices, narrowing down MEI to your very needs. If, for whatever reason, you need a version of MEI that allows
+ you to encode <trill>s, but does not support <mordent>s and <turn>s, you can easily turn off those two elements,
+ but keep the MEI.cmnOrnaments module as such. Looking at "larger" modules like MEI.cmn, MEI.header, or
+ MEI.edittrans, it is easy to envision more practical use cases for this selective exclusion of elements.
+
+
+ As with elements, it is possible to disallow attribute classes in this module overview. However, this requires
+ a good understanding of the available classes and their nesting. For most users (and use cases), it will be more practical to
+ do this from a slightly different perspective. On each element, there is a set attributes-button. If you click that button,
+ the content of the main column is yet again replaced with different content. This time, you will find a listing of all
+ attributes available on that element. The layout of this listing follows the attribute classes that this element is a member of.
+ Each attribute class has a checkbox that can be used to turn it off. If you unselect an attribute class, it will not only
+ remove the attributes defined within that class, but will also suppress all other attribute classes inherited through the class
+ hierarchy – including all attributes defined by those. For instance, if you uncheck the att.basic attribute class (which
+ is available on every element in MEI through the att.common class), this will not only remove the @xml:base
+ attribute, but also the att.id class, and through this the @xml:id attribute. After doing this on any element
+ of your choice, you should navigate to another element. You will notice there that the same attribute class is already turned
+ off: All those options are properly coordinated. This includes the attribute classes listed at the level of individual modules.
+
+
+ With the options to turn off modules, individual elements, and specific attribute
+ classes, it is already possible to restrict the MEI schema considerably, making it a better fit for the specific
+ needs of any given project, and help that project to avoid inconsistency and other encoding problems. As the MEI ProfileDrafter
+ allows to start from multiple official MEI customizations, it is fairly simple to generate a custom version of MEI that further
+ restricts the MEI CMN profile (or any other cusotmization). In the next step of this tutorial, we will see how to make use of
+ this customization.
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/181_customizing_MEI/181_customizing_mei-03.html b/_tutorials-BA/181_customizing_MEI/181_customizing_mei-03.html
new file mode 100644
index 00000000..0cb6d1d3
--- /dev/null
+++ b/_tutorials-BA/181_customizing_MEI/181_customizing_mei-03.html
@@ -0,0 +1,38 @@
+
+
+ As soon as you have created a custom restricted version of MEI with the
+ MEI ProfileDrafter, the next step
+ is to prepare your first MEI Customization for validation – you need to compile it into a RelaxNG file. Whiel the
+ ProfileDrafter will offer such a compiled version for direct download at some point, we will focus on a different compilation
+ method which allows to make further manual changes the ODD customization file. In a professional project setup, you will also
+ want to version and document your ODD customization properly – both of which is out of scope for the MEI ProfileDrafter.
+
+
+ Please hit the Download ODD-button in the left column of the ProfileDrafter and save the offered file to any
+ convenient location. Now direct a new browser window to the
+ MEI Customization Service
+ that is part of the MEI Garage. Here, you need to select the MEI Source file your customization is based on. As the
+ ProfileDrafter is currently restricted to MEI v4.0.1, you can keep the default option in the Customization Service. The next
+ step is to select and upload your Local Customization file in the center column. Then, you need to keep the Output
+ option set to RelaxNG. You can now hit the large Process-button in blue. After some server-side processing,
+ the label of that button will change to Download. As soon as that happens, you can click again to download the
+ resulting RelaxNG file. Please make sure to rename the downloaded file to something meaningful and use
+ the .rng extension. You now have a proper RelaxNG file compiled from your ODD Customization. This file may
+ be used to validate XML files against your custom profile of MEI. Congratulations – you have already made significant
+ progress in how to use MEI. A version specifically tailored for your needs is always preferable over a generic one-size-fits-all
+ profile – which is obviously meant as starting point for more specific adjustments tailored around your needs.
+
+
+ This tutorial could safely stop here. The real challenge is to identify your needs and to
+ model them accordingly anyway, but this is nothing that could be taught by an online tutorial. While getting
+ the necessary experience for this will depend on time and interchange, you already have the technical skills to approach
+ good models.
+
+
+ However, with some additional adjustments to the ODD Customization, it is possible to exersize even better control over the
+ resulting schema, giving you very tight control over validation and thus helping to prevent data errors as much as possible.
+ Such adjustments are out of scope for the ProfileDrafter, and will therefore require manual adjustments to the ODD Customization.
+ In the next step, we will analyze the structures that the ProfileDrafter uses to remove individual modules, elements,
+ and attribute classes from MEI.
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/181_customizing_MEI/181_customizing_mei-04.html b/_tutorials-BA/181_customizing_MEI/181_customizing_mei-04.html
new file mode 100644
index 00000000..808a144a
--- /dev/null
+++ b/_tutorials-BA/181_customizing_MEI/181_customizing_mei-04.html
@@ -0,0 +1,53 @@
+
+
+ You have already learned how to use the
+ MEI ProfileDrafter,
+ and you have used the
+ MEI Customization Service
+ to compile your own customization. You have downloaded an .odd file with that customization. We're assuming your customization
+ takes out some modules, elements, and attribute classes. Let's review how this manifests in the ODD customization
+ file now. Please open it with any convenient XML Editor.
+
+
+ You will find a regular TEI file, with some disclaimers
+ on top, and a <teiHeader> element that may serve as a starting point for providing proper documentation
+ for your customization. You will certainly want to adjust the <respStmt> (responsibility statement) that is
+ usually somewhere around line 27 to claim responsibility. The interesting content starts at line 54 (the exact number may vary).
+ There, we have the <schemaSpec>
+ element, which starts our customization. Let's put aside the attributes specified here, and let's also ignore the
+ <constraintSpec> element for now.
+
+
+ What we see then is a list of <moduleRef>
+ (module reference)
+ elements, each of which refering to an MEI module with it's @key attribute. Only those attributes that you haven't excluded
+ from the schema are listed here. Accordingly, it is very simple to exclude an MEI module from a customization manually: You just need to
+ delete the reference to it in you customization file.
+
+
+ On one or more <moduleRef>s, you should see an additional attribute @except. This attribute holds a
+ list of elements from the specified module, which are to be excluded from the customization. Basically, here you can selectively
+ take out individual elements, while keeping all others from the current module in your customization. ODD also supports the reverse approach of
+ explicitly allowing elements from a module through the @include attribute. It is not allowed to combine both approaches, and
+ according to the TEI Guidelines, ODD processors are requested to raise an error message. The MEI ProfileDrafter will understand both approaches when
+ uploading existing customizations, but will prefer @except over @include when exporting data.
+
+
+ Finally, at the end of your ODD file there will be a list of <classSpec>
+ (class specification)
+ elements with @type="atts". They also use the @ident attribute to identify individual attribute classes. Please note that
+ this element holds no reference to the module this attribute is defined in. Instead, and more importantly, it uses the @mode attribute
+ to specify what should be done to the original MEI sources, which are supposed to be modified by your customization. Here, the only value used will
+ be @mode="delete" – the corresponding attribute classes will be deleted from your customization, making them unavailable in the resulting
+ schema. Again, it is very simple to make such exclusions manually.
+
+
+ As you can see, there is very little that the MEI ProfileDrafter is actually doing in ODD – it is mostly a convenient user interface that
+ helps to illustrate the consequences of removing various components from the schema. For instance, it shows very clearly which attributes on
+ the <note> element will be unavailable when the MEI.gestural module is turned off. Technically, however, it is
+ doing only very simple things one could implement manually equally well.
+
+
+ In the following step, we will introduce some more concepts for ODD customizations, paving the path for even more specific ODD customizations.
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/181_customizing_MEI/181_customizing_mei-05.html b/_tutorials-BA/181_customizing_MEI/181_customizing_mei-05.html
new file mode 100644
index 00000000..23bb42b8
--- /dev/null
+++ b/_tutorials-BA/181_customizing_MEI/181_customizing_mei-05.html
@@ -0,0 +1,79 @@
+
+
+ In the last step, we learned that a <classSpec type="atts" ident="att.basic" mode="delete"/> can be used to delete
+ the att.basic attribute class (like any other) from an MEI customization. The @mode attribute is what determines
+ this behavior here. The TEI Guidelines for the
+ att.combinable
+ attribute class provide additional documentation about allowed values. It reads that "an ODD processor should handle the values for @mode as follows":
+
+
+
add
+
the object should be created (processing any children in add mode); raise an error if an object with the same identifier already exists
+
replace
+
use this object in preference to any existing object with the same identifier, and ignore any children of that object; process any new children in 'replace' mode
+
delete
+
do not process this object or any existing object with the same identifier; raise an error if any new children supplied
+
change
+
process this object, and process its children, and those of any existing object with the same identifier, in 'change' mode
+
+
+ With this, it is possible to not only delete attribute classes through a customization, but also to modify it. For instance, in the
+ MEI Basic customization, the
+ @xml:base attribute is removed from the schema. In the MEI sources, this is defined in the att.basic attribute class:
+
+
<classSpec ident="att.basic" module="MEI.shared" type="atts">
+ <desc>Attributes that form the basis of the att.common class.</desc>
+ <classes>
+ <memberOf key="att.id"/>
+ </classes>
+ <attList>
+ <attDef ident="xml:base" usage="opt">
+ <desc>Provides a base URI reference with which applications can resolve relative URI references into absolute URI references.</desc>
+ <datatype>
+ <rng:ref name="data.URI"/>
+ </datatype>
+ </attDef>
+ </attList>
+</classSpec>
+
+ As you can see, the att.basic class is a member of the att.id class – which is responsible for making the
+ @xml:id attribute available on every element. So, deleting att.basic from the schema would also disallow the use
+ of @xml:ids anywhere in files conforming to the resulting customization – certainly not a good idea in any practical use case.
+ Instead, the flexibility offered through different @modes can be used to make more fine-grained statements here. The following example
+ shows what has been done to customize att.basic for the MEI Basic profile:
+
+
<classSpec ident="att.basic" module="MEI.shared" type="atts" mode="replace">
+ <desc>Attributes that form the basis of the att.common class.</desc>
+ <classes>
+ <memberOf key="att.id"/>
+ </classes>
+</classSpec>
+
+ Instead of mode="delete", it uses mode="replace" to give a new definition for the attribute class. This attribute class
+ then just lacks the attribute definition for @xml:base. Alternatively, it would have been possible to use @mode="change"
+ on the attribute class, leave out the child classes (as a value of change will trigger processing of the original classes as well, see above),
+ and give an additional mode="delete" on the attribute definition, as seen in the following example:
+
+ Both approaches yield the same results, so it is mostly a matter of preference to select a solution. Usually, it is a good approach to copy an
+ existing definition (which is always accessible through the MEI Guidelines) into your customization, and then adjust it by carefully inserting
+ processing @modes to the object itself and its children. @mode can be used on a number of different elements in an ODD
+ customization: <elementSpec>s, <remarks>, <classSpec>s,
+ <memberOf>s,
+ <constraintSpec>s, <macroSpec>s, <attDef>s, <valList>s,
+ and <valItem>s. For instance, the accidental values defined in
+ data.ACCIDENTAL.WRITTEN.basic
+ contain not only values like s (sharp) and f (flat), but also tf (for triple flats). In projects working on material
+ that is lacking such accidentals, it might be a good idea to remove them from the schema altogether, so that no one can enter them without triggering
+ a validation error.
+
+
+ There is one last type of modification that this tutorial is going to cover. You will find it in the next step.
+
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/181_customizing_MEI/181_customizing_mei-06.html b/_tutorials-BA/181_customizing_MEI/181_customizing_mei-06.html
new file mode 100644
index 00000000..42a3c737
--- /dev/null
+++ b/_tutorials-BA/181_customizing_MEI/181_customizing_mei-06.html
@@ -0,0 +1,27 @@
+
+
+ Regular MEI allows the following document elements: <mei>, <meiHead>,
+ <music>, and <meiCorpus>. This means that these elements may serve as outermost
+ elements in an MEI file. However, a project may come up with a data structure that requires other or additional start elements.
+ For instance, a project may decide to keep all editorial annotations as separate files, each containing its own <annot>
+ element. The official mei-all_anyStart
+ customization allows to use every single element in the MEI Namespace as start element, but this is mostly for teaching purposes and is not
+ recommendable for practical use. Instead, ODD offers a simple mechanism to define the allowed start elements, using the initial
+ <schemaSpec> element.
+
+ As you can see, the @start-attribute is used as a space-separated list of all start elements. If the project mentioned above decided
+ to allow <mei> and <annot>, but disallow all other start elements, this could be modified like so:
+
+ As you can see, adjusting start elements is actually quite easy. Let's wrap up what we've learned about customizing ODD.
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/181_customizing_MEI/181_customizing_mei-end.html b/_tutorials-BA/181_customizing_MEI/181_customizing_mei-end.html
new file mode 100644
index 00000000..00bd175c
--- /dev/null
+++ b/_tutorials-BA/181_customizing_MEI/181_customizing_mei-end.html
@@ -0,0 +1,22 @@
+
+
+ You have learned how to use the
+ MEI ProfileDrafter for creating MEI Customizations
+ through a graphical user interface. You have learned that this tool has limited scope, but already allows to restrict MEI considerably.
+ You have learned that the ODD markup generated by the tool is actually pretty simple, and can be done manually equally well. You learned how to
+ use @modes in
+ advanced ODD customizations, and how they allow more fine-grained control over the resulting schema. Along the way, you also learned how to compile
+ an ODD customization into a RelaxNG file that can be used for validation, using the
+ MEI Customization Service.
+
+
+ Of course, there are other ways to compile ODD, there are additional concepts to keep in mind, and the fact that MEI uses an older version of
+ ODD than the TEI (as described in the Understanding ODD tutorial)
+ may cause confusion along the way. Working with ODD is surely a bit odd, but it's definitely worth the effort, as it allows you to use a version of
+ MEI that is very specific to your needs. This will help you to provide proper documentation, which will help others to better understand and use your
+ data. So, writing ODD customizations is definitely a good investment in the sustainability of your research.
+
+
+ A word of warning: This tutorial is pretty much work in progress, and may be organized differently after gathering feedback from a number of workshops.
+
+ Obviously, you care about MEI, and this is wonderful. A good way to make sure you understand
+ MEI properly is to write a tutorial for it, which at the same time helps others to get a
+ better understanding.
+
+
+ Writing documentation is typically an unrewarding task. No matter how much you write, there is
+ always need for more, and no matter what you do, you will never fit the needs and expectations
+ of everyone. The best way to address these issues is therefore to spread the task over many
+ shoulders: There will be less work for everyone, and by looking at MEI from different backgrounds
+ and levels of expertise, it becomes more likely to provide just the right assistance for everyone's
+ specific needs.
+
+
+ So when you've learned something about MEI that you think others may benefit from, please don't
+ hesitate to contribute. This tutorial will explain to you what's needed. No worries, you don't need
+ to be a programmer to write your own tutorial, introduction to a specific repertory, or general best-practice
+ recommendation. The MEI Community is
+ out there to assist you, and the Technical
+ Team will ensure that all you write is technically correct – nothing can go wrong, promised. So please follow
+ us along on the next page by clicking continue below.
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/199_tutorials/199_writing_tutorials-02.html b/_tutorials-BA/199_tutorials/199_writing_tutorials-02.html
new file mode 100644
index 00000000..ae309816
--- /dev/null
+++ b/_tutorials-BA/199_tutorials/199_writing_tutorials-02.html
@@ -0,0 +1,37 @@
+
+
+ Like the rest of our website, all tutorials are served directly from a
+ GitHub repository. This has
+ both benefits and drawbacks. A tremendous benefit is that creating a new tutorial is as easy as
+ committing a folder to the repository (we'll explain that later, no worries). The biggest drawbacks are that
+ the interactivity required for a tutorial isn't very well supported by that technical setup, and that we
+ cannot really validate against the MEI Schema. Both aspects have been addressed by us, and we hope that
+ our solutions balance well between the user's need for guidance and the effort that needs to go into the
+ preparation of a tutorial. We'll come back to that later as well.
+
+
+ Now let's get started. Our pages are build and served by Jekyll.
+ For our tutorials, this means we need a Markdown file
+ with the details about our tutorial that the surrounding website needs to know to embed it properly.
+ Let's have a look at the Markdown file for this very tutorial:
+
+
---
+layout: tutorials
+type: tutorial
+name: "Writing Tutorials"
+fullname: "An Introduction to writing MEI tutorials"
+data: "tutorials.json"
+---
+
+
While the first two lines, layout: tutorials and type: tutorial always need to stay
+ like this, the following two lines may change. What you write in here get's displayed in the list of tutorials,
+ for instance. Please note that the very first and last line, each holding three dashes, must stay like this for
+ the tutorial to function properly.
+
+
+ As I said before, we do have to work around the limitations of our technical setup to some degree. For that
+ reason, we're referencing a file called tutorials.json, which lives in the same folder. The name
+ of the file doesn't matter, as long as it can be found in the same folder as the Markdown file. Let's move on
+ to the contents of this JSON file.
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/199_tutorials/199_writing_tutorials-03.html b/_tutorials-BA/199_tutorials/199_writing_tutorials-03.html
new file mode 100644
index 00000000..4cffe1d7
--- /dev/null
+++ b/_tutorials-BA/199_tutorials/199_writing_tutorials-03.html
@@ -0,0 +1,97 @@
+
+
+ In the JSON file, the contents of a tutorial are
+ coordinated. It has an object with a number of properties. Let's have a look at (a simplified version of)
+ this current tutorial:
+
+ There are three important properties in here. The first one, "steps" is used to describe the different steps in
+ a tutorial. We'll come back to that in a second. The next one, "end", specifies a file in which the final page of a
+ tutorial is provided. Finally, there is "resp". In this array, you're supposed to put in your name
+ and affiliation. That way, we're not only trying to identify a contact person if questions arise, but also to give
+ you some public recognition for the work you're doing on MEI. In case you've worked on a tutorial with a group of
+ people, you may of course enter all of them. So why not ask some of your students to work on these tutorials?
+
+
Steps
+
+ Back to the steps property. This is an array of objects, each describing one step of a tutorial. The only property
+ that is definitely required is "descFile". Here, you need to provide the name of an HTML file containing the instructions
+ for this step. Basically, it's what you currently read. That file is not a full HTML file; it should start with a
+ <div> root element and contains simple HTML.
+ The next property, "label", is optional. If you don't provide it, the step will be labelled according to its
+ position (i.e. "Step 3" or similar).
+
+
+ Obviously, a tutorial is not supposed to be pure text only (that would hardly justify this whole setup…). Sometimes,
+ you may want the user to actually encode things. Let's have a look at the definition of such a "step":
+
+
{
+ "label":"A Sample Step",
+ "descFile": "step-instructions.html",
+ "xmlFile": "encoding.xml",
+ "xpaths": [
+ {
+ "rule":"count(//mei:note) = 1",
+ "renderanyway":false
+ },
+ {
+ "rule":"//mei:note/@pname = 'g'",
+ "renderanyway":true,
+ "hint":"You need a @pname attribute, with a value of g."
+ }
+ ],
+ "editorLines":3,
+ "prefillFile":"prefill.xml"
+}
+
+
+ The two properties we already know are in gray, we don't need to go back to them. If a step contains both an
+ "xmlFile" and an "xpaths" property, an editor will be displayed. At the same time,
+ the "Continue"-button on the lower right will go away. In order to proceed, the user now has to follow your
+ instructions and enter the MEI code in the editor. In order to decide if the user has succeeded or not, you
+ need to provide a number of XPath rules. The XPath itself is
+ stored in a "rule" property. It has to return a boolean value, i.e. true or false.
+ If you want to guide the user, you may provide a "hint" property. If the editor's content doesn't
+ match an XPath rule, it's hint will be rendered as a warning box below the editor. XPath rules are checked in
+ order, and further checking is stopped on every falsy rule. If all rules are matched, the tutorial will
+ automatically continue to the next step.
+
+
+ The "renderanyway" property of an XPath rule is useful when you want the user to "play around" with
+ the encoding. Normally, the users input is rendered only when all XPath rules are matched. However, you could
+ ask the user to try out different pitches, saying that the tour continues when a specific pitch is entered.
+ Then, you may set "renderanyway" to true, and Verovio will try it's best in rendering
+ the current user input. This behaviour is implemented in the second XPath rule above.
+
+
+ The "xmlfile" property specifies a file that serves as context for the editor. In the next step
+ of this tutorial, we'll explain this in greater detail. There are two more properties that might be useful.
+ With the "editorLines" property, you can specify the height of the editor window. If you don't
+ provide it, a default height of 5 lines will be assumed. Finally, you can prefill the editor at the beginning
+ of a step with the contents of a file you specify with the "prefillFile" property. If you don't provide
+ that, the editor will keep the input the user has entered in the previous step (or it will be empty on the first one).
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/199_tutorials/199_writing_tutorials-04.html b/_tutorials-BA/199_tutorials/199_writing_tutorials-04.html
new file mode 100644
index 00000000..e6392dc3
--- /dev/null
+++ b/_tutorials-BA/199_tutorials/199_writing_tutorials-04.html
@@ -0,0 +1,56 @@
+
+
+ When doing a tutorial by yourself, you may have wondered how Verovio is able to render the user's MEI,
+ even though not a complete MEI file is entered by the user. This is achieved by the "xmlFile"
+ property of a tutorial step introduced on the last page. This property references a complete MEI file,
+ which provides the context that needs to go "around" the user's input for correct rendering. Let's look at
+ a simple example:
+
+ This is just a regular MEI file, but it contains two important processing instructions
+ (marked in red). The content of this file is read into memory. Whenever the user input in the editor
+ is well-formed XML, it is inserted between the two processing instructions, and the complete
+ file (now including the user input) is validated and (if applicable) sent to Verovio for rendering.
+
+
+ What is stored between the two processing instructions is intended to serve as sample solution.
+ That functionality isn't implemented yet, but will be added soon. It is already possible to download
+ the complete file (including the context), so that users may use them for future reference or as model
+ for their own work.
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/199_tutorials/199_writing_tutorials-05.html b/_tutorials-BA/199_tutorials/199_writing_tutorials-05.html
new file mode 100644
index 00000000..3e4535a2
--- /dev/null
+++ b/_tutorials-BA/199_tutorials/199_writing_tutorials-05.html
@@ -0,0 +1,41 @@
+
+
+ Obviously, proper input validation is crucial for an effective and sustained learning success.
+ Because our website is based on Jekyll, however, we have to rely on client-side validation
+ (relying on an external service for validation only is probably not reliable enough, so we decided
+ against that approach). To this date, client-side validation (= Javascript) doesn't offer proper
+ support for RelaxNG, the schema language
+ ultimately used to validate MEI instances in real projects. For this reason, we need to use the
+ XPath-based approach mentioned earlier.
+
+
+ The "xpaths" property of the current step holds an array of rules to which the user's encoding must
+ conform in order to complete that step. These rules are specified as JSON objects with three properties:
+
+
{
+ "rule":"//mei:note/@pname = 'g'",
+ "renderanyway":true,
+ "hint":"You need a @pname attribute, with a value of g."
+}
+
+ The "rule" property holds an XPath 1
+ expression, which must resolve to a boolean statement: it has to be
+ either true or false. The "renderanyway"
+ is used to decide if the current editor can be rendered by Verovio
+ even if the XPath isn't matched. The content of "hint"
+ is supposed to assist the user to reach the correct encoding. Only
+ the first failing XPath will be displayed at a time, guiding the
+ user step by step through the different requirements. However, not
+ every step needs a hint – sometimes it's better to let the user
+ explore a bit on his own.
+
+
+ For validation, the current user input will be inserted between the
+ <?snippet-start?> and <?snippet-end?>
+ markers in the current XML file, and then the XPath rules will be
+ checked against that complete file. As soon as one of these rules fails
+ (i.e. returns false), the corresponding "hint"
+ will be displayed. When all rules return true, the "continue"
+ button will be enabled and the user may proceed to the next step.
+
+
\ No newline at end of file
diff --git a/_tutorials-BA/199_tutorials/199_writing_tutorials-end.html b/_tutorials-BA/199_tutorials/199_writing_tutorials-end.html
new file mode 100644
index 00000000..312d9642
--- /dev/null
+++ b/_tutorials-BA/199_tutorials/199_writing_tutorials-end.html
@@ -0,0 +1,18 @@
+
+
+ That's it. You just need to write a bunch of files, and commit them to the MEI website, in the
+ tutorials
+ folder. Ideally, you will prepare the tutorial in your own branch, and then send a pull request to the MEI repository
+ and ask for reviews by some of the Technical Team.
+ Of course, we're happy to assist you – just contact us.
+ To get a headstart, you may want to copy an existing tutorial and modify that to your needs. The
+ 101_quickstart tutorial should be a good starting point, as it is very simple, but still holds all relevant
+ features.
+
+
+ Thanks for reading all this. Thanks even more for considering to write a tutorial for MEI. Your input can definitely make
+ a difference. Even though you may not be sure if you're sufficiently familiar with MEI, you can surely share some
+ of your insights with others. Even if you just have an idea for what should be covered by tutorial, please step up, so
+ that maybe we can build it together – as a community, for the community.
+
+
diff --git a/_tutorials-BA/199_tutorials/199_writing_tutorials.json b/_tutorials-BA/199_tutorials/199_writing_tutorials.json
new file mode 100644
index 00000000..6722f929
--- /dev/null
+++ b/_tutorials-BA/199_tutorials/199_writing_tutorials.json
@@ -0,0 +1,31 @@
+{
+ "steps": [
+ {
+ "label":"Welcome",
+ "descFile": "199_writing_tutorials-01.html"
+ },
+ {
+ "label":"Website Setup",
+ "descFile": "199_writing_tutorials-02.html"
+ },
+ {
+ "label":"The JSON file",
+ "descFile": "199_writing_tutorials-03.html"
+ },
+ {
+ "label":"The Editor",
+ "descFile": "199_writing_tutorials-04.html"
+ },
+ {
+ "label":"Validation",
+ "descFile": "199_writing_tutorials-05.html"
+ }
+ ],
+ "end":"199_writing_tutorials-end.html",
+ "resp":[
+ {
+ "name":"Johannes Kepper",
+ "affiliation":"Beethovens Werkstatt | Universität Paderborn"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/_tutorials-BA/199_tutorials/199_writing_tutorials.md b/_tutorials-BA/199_tutorials/199_writing_tutorials.md
new file mode 100644
index 00000000..5011119b
--- /dev/null
+++ b/_tutorials-BA/199_tutorials/199_writing_tutorials.md
@@ -0,0 +1,7 @@
+---
+layout: tutorials
+type: tutorial
+name: "META: Writing Tutorials"
+fullname: "An Introduction to writing MEI tutorials"
+data: "199_writing_tutorials.json"
+---
diff --git a/resources/tutorials-BA.md b/resources/tutorials-BA.md
new file mode 100644
index 00000000..f6f6b385
--- /dev/null
+++ b/resources/tutorials-BA.md
@@ -0,0 +1,23 @@
+---
+layout: tutorials-BA
+title: "MEI tutorijali"
+---
+# MEI tutorijali
+
+Na ovoj stranici ćete pronaći niz malih tutorijala za MEI,
+svaki od njih predstavlja određenu karakteristiku.
+
+Ako namjeravate početi učiti MEI, preporučujemo da počnete s [5-minutnim vodičem](/tutorials-BA/101-quickstart), koji će vam omogućiti da kodirate vrlo jednostavnu melodiju pomoću MEI.
+
+Ako nameravate da napišete novi MEI tutorijal, preporučujemo da počnete sa vodičem [Pisanje tutorijala](/tutorials-BA/tutorials), koji će vam pružiti pozadinu o potrebnim koracima. Također pogledajte našu listu tutorijala koji nedostaju na [Github](https://github.com/music-encoding/music-encoding.github.io/issues/88).
+
+### Eksterni tutorijali i srodni materijal
+
+Za resurse stvorene u zajednici, uključujući tutorijale i nastavni materijal, pogledajte [Community-Created Pedagogy & Praxis Resources](/resources/pedagogy.html).
+
+Za španski prijevod tutorijala, pogledajte [Tutoriales en español](/resources/tutorials-ES.html).
+Za engleski prijevod tutorijala, pogledajte [Tutorials on English](/resources/tutorials.html).
+
+
+----
+*Prevod tutorijala je realizovala Olja Janjuš u martu 2024.
\ No newline at end of file