★ Conformance
This page defines what conformance means in ThaiMusicXML v1.0 and collects the rules that the element pages state individually.
Requirement keywords
Section titled “Requirement keywords”The keywords must, must not, should, should not, and may carry their usual specification meanings:
- must and must not are absolute requirements. A document that breaks one is not a ThaiMusicXML document.
- should and should not describe behaviour with good reasons behind it. Ignore them only with the full implications understood.
- may marks something genuinely optional. A processor that does not implement it stays conforming.
Conforming document
Section titled “Conforming document”A conforming ThaiMusicXML v1.0 document:
- Is a well-formed XML document.
- Has a single
<thai-score>root carryingversion="1.0"and the ThaiMusicXML namespace. - Satisfies every must rule on every element page.
A RELAX NG schema states the rules a grammar can reach. The rest stay prose, and checking them takes a second pass over the document.
Conforming processor
Section titled “Conforming processor”A processor is anything that reads ThaiMusicXML: a validator, a renderer, a player, a converter.
A conforming processor must reject documents that break a must rule, or report the violation clearly if it chooses to carry on. It must not silently repair one. Where a rule says validators should warn, a processor is expected to accept the document and say something.
A processor may ignore anything it has no use for. A validator with no audio output can skip <tuning>; a converter with no display can skip everything in the Rendering reference.
Warn on anything discarded
Section titled “Warn on anything discarded”Several rules in this spec resolve a conflict by ignoring one side of it rather than rejecting the document. Wherever that happens, a validator should warn.
The author wrote something, and the file behaves as though they had not. That is worth a word even when it is harmless, because the alternative is a document that validates clean while quietly not saying what its author meant. octave beside a Thai octave modifier, octave on a note using sound, and text sitting beside <text> children are all cases of it.
This is a general principle rather than a rule of its own. Where a specific element page states the warning, that page is the authority.
Lexical types
Section titled “Lexical types”The element pages name a type for each attribute. This section says what those names accept, so that two parsers written from this spec agree on what a legal value looks like.
Booleans
Section titled “Booleans”true, false, 1, and 0, matched by value. dim="1" and dim="true" are the same. Nothing else is accepted.
Integers
Section titled “Integers”An optional sign followed by digits. octave takes any integer; times, first, last, number, row, and the content of <bpm> take positive ones, with the bounds each element page gives. times is the one with a floor above 1: it must be 2 or more.
Enumerations
Section titled “Enumerations”<chan>’s value is a closed enumeration, matched exactly as written: 0.5, 1, 2, 3, 4, and neither 0.50 nor .5. Its five levels are the whole set, so anything else is an error.
<nathap>’s value and <tuning>’s reference are open. Both take any non-empty string, and both publish a recommended list. A validator warns on a value outside that list and must not reject it, which catches a misspelling of a known name without turning an unusual one into an invalid document.
One base-note character, optionally followed by one Thai octave modifier.
| Degree | Numeric | Thai | Thai code point | Romanized |
|---|---|---|---|---|
| 1 | 1 |
ด | U+0E14 | D or d |
| 2 | 2 |
ร | U+0E23 | R or r |
| 3 | 3 |
ม | U+0E21 | M or m |
| 4 | 4 |
ฟ | U+0E1F | F or f |
| 5 | 5 |
ซ | U+0E0B | S or s |
| 6 | 6 |
ล | U+0E25 | L or l |
| 7 | 7 |
ท | U+0E17 | T or t |
The two modifiers are นิคหิต U+0E4D, raising an octave, and พินทุ U+0E3A, lowering one. Either attaches to any of the three spellings.
Match on the code points. Both modifiers are combining characters, so in rendered prose they sit on top of whatever precedes them, cannot be distinguished by eye from several lookalikes, and cannot be copied out of a web page reliably.
Normalization is not a concern. Thai has no canonical compositions, so a pitch value is the same sequence of code points under NFC, under NFD, and as authored. No normalization pass is needed before matching.
Comma-separated integers, in ascending order, with no repeats: 2 and 2,4 are well formed, 4,2 and 2,2 are not. See <ending> for the bounds.
id and IDREF
Section titled “id and IDREF”An id is any run of characters with no whitespace in it, and two ids are the same when they match character for character. id="s1" and id="S1" are different ids; id="s 1" is not an id at all, because a value needing to be trimmed or collapsed before matching would resolve one way in a processor that did that and another way in one that did not.
An id must be unique among elements of its own kind. <part id="…"> values must be unique across all parts and <section id="…"> values unique across all sections, but the two sets are independent, so a <part id="1"> and a <section id="1"> may both exist and refer to different things. An IDREF resolves within the kind its attribute names: part on <part-data> finds a <part>, section on <section-ref> finds a <section>.
<line>, <measure>, <note>, <rest>, and <group> also accept an optional id, each kind its own independent set the same way part and section are. Nothing inside ThaiMusicXML itself resolves one - no IDREF attribute names these kinds - since a document has no reason to point at its own note. They exist so a foreign-namespace extension or some other tool outside the document has a stable handle to attach state to, which is also why nothing requires them: a file with none of these ids is as conforming as one with every note tagged.
Foreign-namespace extensions
Section titled “Foreign-namespace extensions”<thai-score> accepts foreign-namespace elements after the last <part-data>, an escape hatch for a third-party tool to carry its own state alongside the score - an editor recording <nts:editor version="1">, say. Each must commit to a real namespace: an unprefixed element in no namespace is rejected, since that would let a tool’s own markup pass as native.
The rule applies at every depth, not just to the element directly under <thai-score>. A processor that walks the whole document by namespace and name must never find something that looks like a ThaiMusicXML element inside an extension, so an unprefixed grandchild inheriting ThaiMusicXML’s own default namespace is rejected exactly like an unprefixed top-level extension is. Declaring a default namespace once, on the extension’s own root, covers every unprefixed descendant beneath it - nothing has to be individually prefixed.
A processor must preserve an extension element it does not recognize, unchanged, across a round trip, and an extension must never affect how the document renders or plays. Those two rules are what let more than one tool’s extensions sit side by side without either needing to understand the other, and what stops an extension from forking the format by becoming load-bearing.
Text and mixed content
Section titled “Text and mixed content”Where an element takes either plain text or <text> children - <annotation>, <composer>, <lyricist>, <arranger> - the <text> children win. Any text beside them is ignored, which is what allows the element to be indented over several lines without its own formatting becoming content. Ignored text that is not merely whitespace draws a warning.
Rules by area
Section titled “Rules by area”Document shape
Section titled “Document shape”<thai-score>must be the single root element, carryingversionand the namespace.- A processor must reject a document whose root is in a namespace it does not implement. The namespace URI names the compatibility boundary: through 0.x each release carries its own, and from 1.0 the URI carries the major version alone.
versiontells releases apart within a boundary and is informational to a processor that already understands the namespace, so a mismatch between the two draws a warning rather than a rejection. - Its children appear in order:
<header>,<structure>,<ensemble>, one or more<part-data>, then zero or more foreign-namespace extension elements. <structure>and<repeat>take<annotation>,<br>,<direction>,<section>,<play>, and<repeat>, in any order.<header>must contain exactly one<title>. Everything else in the header is optional, and<tuning>and<license>appear at most once each.<nathap>,<chan>, and<bpm>are each optional within a<direction>and appear at most once each, in any order.
Identity and reference
Section titled “Identity and reference”- Every
<part>must have exactly one<part-data>referencing it throughpart. - Every
<section-ref>must reference a<section>that exists in<structure>throughsection. - Every
<play>must reference a<section>that exists in<structure>.<play>adds a play of that section to the score’s order without declaring one, so a section is still declared by exactly one<section>. <part-data>elements may appear in any order. A<part-data>must not reference the same section twice, and need not reference every section.- A
<part-data>’s<section-ref>elements may also appear in any order, and that order means nothing. What order the sections play in is<structure>’s to say; a<section-ref>only says which section a run of lines belongs to. - A
<section>that no<part-data>references has no music. It is not played, contributes no rows to the page, and the rules below that count its lines and measures do not apply to it. - A
<part>withstackmust also haverow, and vice versa. Astackvalue must be shared by at least two parts, theirrowvalues must run from1upward with no gaps or repeats, and they must be adjacent in<ensemble>in ascendingroworder. - A
type="lyric"part must not carrystackorrow. A stack is one instrument’s own rows, and words are not a region of an instrument.
Timing
Section titled “Timing”- All
<section-ref>elements referencing the same<section>must agree on line count, on measure count per line, and on beat count per measure. Validators must reject documents that violate this. - A
type="lyric"part is bound by line count and measure count per line, and exempt from beat count per measure. Its measures hold any number of items, and it is excluded from the comparison other parts are held to. - A
<line>must hold one to eight<measure>elements. numberon<line>and<measure>must match position, counting from1, in ascending order.- A measure in a pitched or unpitched part must hold at least one
<note>,<rest>, or<group>. A lyric measure may be empty. - A
<group>must hold at least two<note>or<rest>children, and must not contain another<group>. - A beat arrives on its last slot, so a
<group>’s final child falls on the beat and the earlier ones space backwards from it within the beat’s own span. A group can never reach outside its beat, and so never outside its measure. See<group>.
Repetition
Section titled “Repetition”timeson<repeat>and<line-repeat>must be an integer of2or greater, and defaults to2. It counts total plays, not extra plays on top of the first. An element that played its content once would repeat nothing, sotimes="1"is rejected rather than treated as a no-op.- A
<repeat>must contain at least one<section>or<play>, directly or nested. <line-repeat>requires bothfirstandlast, withfirstno greater thanlast, andlastno greater than the section’s line count.- Two
<line-repeat>ranges in one section must be properly nested or wholly disjoint. <ending>is valid only when the section’s total pass count exceeds1. Everypassvalue must fall within that count, every<line number="N">must replace an existing line, and the replacement must match the original’s measure count. In a notated part it must match the beat counts too - except that a measure left completely empty means “unchanged from the line being replaced”, regardless of that measure’s own beat count. See<ending>’s “Unchanged measures”.- A lyric part’s
<ending>matches on measure count alone, the same exemption it has everywhere else. See Varying the words. - An
<ending>’s lines must form a consecutive run ending on the section’s last line. An ending over the middle of a section is invalid, since the section would carry on normally afterwards and so would not be ending on the variation. - Every
<ending>must carry at least one<annotation>captioning the variation.
Notes and pitch
Section titled “Notes and pitch”typeon a<part>must be"pitched","unpitched", or"lyric". Validators must reject any other value.- A measure’s children must match its part’s
type:<note>,<rest>, and<group>in a pitched or unpitched part,<syllable>and<rest>in a lyric part.<note>,<group>,<bow>,<parenthesis>, and<link>are not valid in a lyric part, and<syllable>is not valid outside one. - A note in a
pitchedpart usespitch; one in anunpitchedpart usessound. The two are mutually exclusive. pitchmust be one of the seven base-note characters in any of the three spellings, optionally followed by one Thai octave modifier. Validators must reject any other value. See Lexical types.- A romanized base note may be written in upper or lower case. Case carries no meaning, and the renderer decides which case appears on the page.
- When
pitchcarries a Thai octave modifier, that modifier wins andoctaveis ignored. Validators should warn rather than reject. <chan>’svaluemust be one of the five listed levels, matched exactly. Validators must reject any other value.<nathap>’svalueand<tuning>’sreferenceaccept any non-empty string. Validators should warn on a value outside the recommended list on the element’s page, and must not reject it.<bpm>content must be a positive integer.- A
<link>span is valid in any notated part. Where the containing<part>has astack, the curve reaches that instrument’s other rows; where it has none, the curve marks the span’s own notes. Either way there is a row for it to reach, since a stack is made of notated parts only.
Span markers
Section titled “Span markers”<bow>,<parenthesis>, and<link>markers pair in document order within a resolved pass. The three kinds are matched independently of one another, so a span of one kind may open inside a span of another. Resolve the section’s<ending>substitutions for a pass, then match within the lines that pass actually plays. See Spans across an overridden line.- A
<line-repeat>does not affect matching. The lines are read once, in the order they are written, however many times playback runs through them. - On every resolved pass, a
type="start"must be closed by a matchingtype="stop"before anotherstartappears. Spans cannot nest or overlap. - On every resolved pass, each
startmust have a matchingstopwithin the same<section-ref>. A span left open at the end of a pass is invalid even if another pass closes it, and spans cannot cross section boundaries. directionis required on<bow type="start">and must not appear ontype="stop".dimandmuteare valid only on<parenthesis type="start">.<link>carries no attribute buttype, on either marker.- A
<link>,<bow>, or<parenthesis>marker inside a<group>has zero duration and does not count toward the equal division of that group’s beat.
Annotations
Section titled “Annotations”alignis required on every<text>and must be"left","center", or"right". A<text>must hold text only, with no child elements.- An
<annotation>may hold at most one<text>peralignvalue. Where it has<text>children they are its content, and any text beside them is ignored with a warning. <composer>,<lyricist>, and<arranger>follow the same rule. Their plain-text default is centered rather than left.- An
<annotation>or<br>inside a<repeat>is printed once, at its position in the document, and is not repeated per pass. A<direction>is re-read on every pass. - A
<line>’s<annotation>children come before its measures. An annotation between two measures is invalid.