Schema และชุดทดสอบ
สิ่งที่มาพร้อมข้อกำหนดนี้มีสามอย่าง: Schema ที่ตัวตรวจสอบอ่านได้ Schema เดียวกันในอีกรูปแบบ และชุดข้อมูลสำหรับทดสอบการนำไปใช้
/schema/thaimusicxml-1.0.rng
คือ Schema เป็น RELAX NG ในรูปแบบ XML xmllint และเครื่องมืออื่นที่ใช้ libxml2
อ่านได้โดยไม่ต้องแปลง:
xmllint --noout --relaxng thaimusicxml-1.0.rng score.txml/schema/thaimusicxml-1.0.xsd
คือ Schema เดียวกันที่แปลงเป็น W3C XML Schema สำหรับเครื่องมือที่อ่าน XSD แต่ไม่อ่าน RELAX NG
สร้างจากไฟล์ .rng โดย Trang ทุกครั้งที่ push
ไฟล์ RELAX NG เป็นไฟล์ที่แก้ไขโดยตรง ส่วน XSD ถือเป็นผลลัพธ์ที่มาทีหลัง
ชุดข้อมูลอยู่ภายใต้ /corpus/ แบ่งเป็นไฟล์ที่ต้องยอมรับและไฟล์ที่ต้องปฏิเสธ ทั้งสองเป็นไฟล์คงที่ ดาวน์โหลด ชี้ตัวตรวจสอบของคุณไปที่ไฟล์เหล่านั้น แล้วดูว่าตรงกันหรือไม่
Schema ครอบคลุมอะไร และไม่ครอบคลุมอะไร
หัวข้อที่มีชื่อว่า “Schema ครอบคลุมอะไร และไม่ครอบคลุมอะไร”ไวยากรณ์อธิบายเอกสารทีละรายการ องค์ประกอบต่อองค์ประกอบ ซึ่งเข้าถึงได้มากกว่าที่คิด: Schema จับการสะกด pitch ที่ไม่รู้จัก ค่า chan เป็น 0.50 ที่ต้องเป็น 0.5 เท่านั้น <bow type="stop"> ที่มี direction ที่ไม่ควรมี <measure> ที่เก้าใน <line> <group> ที่มีลูกเดียว และ <part> ที่มี stack แต่ไม่มี row
สิ่งที่เข้าถึงไม่ได้คือสิ่งที่ขึ้นอยู่กับส่วนอื่นของเอกสาร <measure> จะมีลูก <syllable> ได้หรือไม่ขึ้นอยู่กับ type ของ <part> ที่ประกาศที่อื่นในไฟล์ สองพาร์ตตรงกันเรื่องจำนวนจังหวะหรือไม่เป็นการเปรียบเทียบสองสาขา <ending> ระบุรอบที่มีอยู่หรือไม่ขึ้นอยู่กับจำนวน <repeat> ที่ครอบท่อน หลายระดับขึ้นไป
การสอดคล้องมาตรฐานจึงมีสองชั้น การผ่าน Schema เป็นชั้นแรก ไม่ใช่ทั้งหมด หน้าการสอดคล้องมาตรฐาน ระบุทุกกฎ scripts/check-corpus.mjs ในคลังเก็บทำงานกฎที่ไวยากรณ์ไม่สามารถแสดงออก และรันทั้งสองชั้นบนชุดข้อมูล
สิ่งที่ละไว้โดยเจตนาหนึ่งอย่างควรกล่าวถึง Schema ไม่ประกาศแอตทริบิวต์ id เป็น xsd:ID แม้จะได้การตรวจสอบความซ้ำฟรี เพราะ xsd:ID ซ้ำทั้งเอกสาร แต่ ThaiMusicXML ขอบเขต id ตามประเภท: <part id="1"> และ <section id="1"> เป็นชื่อคนละตัวไม่ชนกัน ความซ้ำถูกตรวจสอบตามประเภทนอกไวยากรณ์
ไฟล์ที่ถูกต้อง
หัวข้อที่มีชื่อว่า “ไฟล์ที่ถูกต้อง”ทุกไฟล์ที่นี่ต้องถูกยอมรับ ทั้งหมดทดสอบกลุ่มที่ยึดขวา เครื่องดนตรีที่ซ้อนแถว พาร์ตเนื้อเพลง ช่วงที่ข้ามขอบเขตห้องและบรรทัด การซ้ำซ้อน และท่อนแปรผัน
| File | What it exercises |
|---|---|
aligned-text.txml | Aligned text runs. An annotation carries all three positions on one line; the credits each carry one. The text prints exactly as written, which is why the label is part of the string rather than generated. Note that the three positions are placed independently, so document order does not decide where they land. |
ending-inherits-empty-measure.txml | A completely empty <measure> inside an <ending> line means "unchanged from the line being replaced" - the arranger only has to write out the measures that actually differ. Measure 1 here is left empty on pass 2, so it plays measure 1 of the base line 2 unchanged; only measure 2 actually varies. |
ending-with-span.txml | A bow span reaching into a line an ending overrides. The stop appears in both versions of line 2: once in the regular line for the pass that plays it, once in the ending's line for the pass that plays that instead. Neither pass sees two stops, because neither pass plays both versions. |
extensions-and-ids.txml | Optional ids on line, measure, note, rest, and group, plus a foreign-namespace extension element after the last <part-data>. |
line-annotation.txml | Annotations at both scopes in one part: one on the <section-ref>, which heads the section, and one on a <line>, which heads that line wherever it falls. A line annotation takes <text> children like any other. |
line-repeats.txml | Line repeats. One range nests inside another and a third is disjoint from both, which is the only arrangement allowed: ranges must be properly nested or wholly separate. A line repeat is independent of any <repeat> around the section and does not affect how spans are matched. |
link-across-beats.txml | A link span reaching past one beat. The markers sit either side of two groups, so the run they mark is four notes long - the case a boolean on <group> could not express, since a group is only ever one beat. The second span opens inside a group and closes inside the next one. |
link-single-row.txml | A link span in a part with no stack. There is no other row to reach, so the curve marks the span's own notes. |
lyric-ending.txml | A lyric part varying its words on the second pass. The ending's measure holds two syllables where the line it replaces holds one syllable and a rest: a lyric part's item count is its own business in an ending as anywhere else, and only the measure count has to match. |
lyric-part.txml | A lyric part beside an instrumental one. Measure 1 has four items and so aligns to the beats; measure 2 has three and is centered in the cell instead. The rests are เอื้อน: no new syllable begins, the vowel already being sung carries on. A lyric part shares the line and measure grid but is exempt from agreeing on beat count. |
minimal.txml | The smallest legal ThaiMusicXML document: one part, one section, one line, one four-beat measure. |
pitch-spellings.txml | The three interchangeable spellings of a base note, the two Thai octave modifiers, and the octave attribute. Measure 1 is numeric, measure 2 romanized (mixed case, which carries no meaning), measure 3 Thai script, measure 4 the modifiers and octave. A real file picks one spelling and keeps to it; this one exercises all of them on purpose. |
repeats-and-endings.txml | Nested repeats and a variant ending. The section sits inside a times="2" within another times="2", so its total pass count is 4 and pass numbers run 1 to 4 absolutely, regardless of which layer produced each play. The ending replaces the section's last line on passes 2 and 4. |
right-anchored-groups.txml | Right-anchored subdivision. Both parts agree on four beats per measure while filling them differently: P1 plays four plain notes, P2 splits beats 1 and 3 into groups. A group's final child lands on the beat and the earlier ones space backwards from it. |
section-omitted-by-part.txml | A part that sits out a section. P2 is silent for the whole of ท่อน 2, so its part-data simply has no section-ref for it. The cross-part agreement rule then applies only to the parts that do reference the section. |
section-replayed.txml | ABA form through <play>: ท่อน 1 is declared once and played twice, the second time after ท่อน 2, without a second copy of its music. That gives it two passes, so it can carry an <ending> for the return. |
spans.txml | Bow and parenthesis spans. The bow in line 1 crosses a measure boundary; the bow opened at the end of line 1 closes in line 2, which renders as two arcs but is one span. The parenthesis span sits inside a group, showing that markers carry no duration and do not count toward the group's division. |
stacked-instrument.txml | A two-row instrument. Both parts share a stack value and number their rows from 1, and they sit adjacent in <ensemble> in row order. A link span in row 1 draws a connector to what row 2 plays over the same beats. Each row also carries an instrument-short-name, since the ensemble label column has only the page margin to work with. |
unpitched-part.txml | An unpitched part. Notes carry sound rather than pitch, and the codes are instrument-specific, so an annotation inside the section reference says what they mean. The rests are beats with no attack. |
version-mismatch.txml | A conforming document whose version attribute disagrees with its namespace. The namespace is the compatibility boundary, so this is read as 1.0 and draws a warning rather than a rejection. |
warnings.txml | A valid document that a conforming processor should nevertheless warn about, four times over. Nothing here makes the file invalid: the rule in each case is warn, never reject. - nathap and tuning carry values outside the recommended lists, which is legal because neither set is closed, but catches a typo in a known name - the composer has <text> children, so the text beside them is discarded rather than printed - octave sits alongside a Thai octave modifier, where the modifier wins - octave sits on a note that uses sound, where it has no meaning |
warnings.txml เป็นกรณีพิเศษ เป็นเอกสารที่สอดคล้องมาตรฐานแต่ตัวประมวลผลควรแจ้งเตือนห้าครั้ง เพราะทุกกฎที่แตะเป็นกฎที่ข้อกำหนดระบุว่าแจ้งเตือนแทนปฏิเสธ
ไฟล์ที่ไม่ถูกต้อง
หัวข้อที่มีชื่อว่า “ไฟล์ที่ไม่ถูกต้อง”ทุกไฟล์ที่นี่ต้องถูกปฏิเสธ แต่ละไฟล์ละเมิดกฎเดียวเพื่อให้ความล้มเหลวชี้ไปจุดที่เจาะจง ความเห็นด้านบนไฟล์ระบุกฎที่ละเมิด
ไฟล์เหล่านี้เป็นตัวอย่างตรงข้าม ไม่ใช่ต้นแบบ ไม่มีไฟล์ใดในไดเรกทอรีนี้เป็นไฟล์ที่ควรคัดลอก
| File | What it violates |
|---|---|
beat-count-mismatch.txml | Corresponding measures must agree on beat count across parts. P1 has four beats where P2 has three. |
bow-span-unclosed.txml | A bow start must be closed by a stop within the same section reference. This span is left open at the end of the pass. |
bow-spans-overlap.txml | A bow start must be closed before another start appears. Bow spans cannot nest or overlap. |
bow-start-without-direction.txml | direction is required on a bow start. |
bow-stop-with-direction.txml | direction must not appear on a bow stop. The span already carries its direction from the start. |
bow-stop-without-start.txml | A bow stop with no open span before it. |
bpm-zero.txml | bpm content must be a positive integer. |
chan-value-not-exact.txml | chan is a closed enumeration matched exactly. "0.50" is not "0.5". |
duplicate-note-id.txml | Two notes share an id. Ids are unique within their own kind, the same rule as part and section ids, extended to note. |
duplicate-part-id.txml | Two parts share an id. Ids must be unique within their kind. |
duplicate-section-id.txml | Two sections share an id. |
ending-beat-count-differs.txml | Corresponding measures in an ending line must keep the beat count of the line they replace. Only the notes inside may vary. |
ending-duplicate-line-for-pass.txml | Two endings must not cover the same line number for the same pass. |
ending-line-not-trailing.txml | An ending's lines must form a consecutive run through to the section's last line. This one covers line 2 of a three-line section and then stops. |
ending-line-number-missing.txml | Each line in an ending must match the number of a line already present in the section-ref. There is no line 4. |
ending-measure-count-differs.txml | An ending line must have the same number of measures as the line it replaces. |
ending-on-unrepeated-section.txml | An ending is only valid in a section whose total pass count is greater than 1. This section plays once. |
ending-pass-descending.txml | pass values must be listed in ascending order with no repeats. |
ending-pass-exceeds-total.txml | pass values must fall within the section's total pass count, which is 2 here. |
ending-pass-zero.txml | pass numbers are 1-based. Zero is not a pass. |
ending-without-annotation.txml | An ending must carry at least one annotation. It prints away from the line it replaces and needs a caption saying which part it belongs to and when it applies. |
extension-without-namespace.txml | An extension element after <part-data> with no namespace of its own, indistinguishable from native markup. |
group-nested.txml | Groups do not nest. Subdivisions in v1.0 go one level deep. |
group-one-child.txml | A group must contain at least two note or rest children. There is nothing to subdivide a beat between here. |
header-out-of-order.txml | header children are ordered. title comes first. |
id-with-whitespace.txml | an id containing a space. Ids are matched character for character, so they carry no whitespace: an id that had to be trimmed or collapsed before matching would resolve differently in two processors. |
line-annotation-after-measure.txml | a <line>'s annotations come before its measures, the same order <section-ref> uses. One sitting between two measures is rejected. |
line-count-mismatch.txml | All section-refs for one section must agree on line count. |
line-nine-measures.txml | A line holds between one and eight measures. Eight is a hard limit; this line has nine. |
line-number-out-of-order.txml | number must match the line position, counting from 1, and lines must appear in ascending order. |
line-repeat-duplicate-range.txml | Two line-repeat elements covering the identical range. Combine them into one with a higher times. |
line-repeat-first-after-last.txml | first must be less than or equal to last. |
line-repeat-last-exceeds-lines.txml | last must not exceed the number of lines in the section's content. |
line-repeat-partial-overlap.txml | Two line-repeat ranges must be properly nested or wholly disjoint. These partially overlap. |
line-repeat-times-one.txml | times="1" on a line-repeat. A range played once is not repeated, and a bare <line-repeat> already means twice. |
line-repeat-times-zero.txml | times must be an integer of 1 or greater. |
link-span-unclosed.txml | A link start must be closed by a stop within the same section reference. This span is left open at the end of the pass. |
link-spans-overlap.txml | A link start must be closed before another start appears. Link spans cannot nest or overlap. |
link-stop-without-start.txml | A link stop closes no open span. Every stop needs a start before it. |
lyric-measure-holds-note.txml | A lyric part's measures hold only syllable and rest. |
lyric-measure-holds-only-notes.txml | A lyric part's measures hold syllable and rest. This measure holds notes, which the grammar accepts on its own because a part's type is declared in <ensemble>, out of the grammar's reach. |
lyric-part-with-stack.txml | a lyric part carries stack. A stack is one instrument's own rows, and words are not a region of an instrument, so a lyric part sits beside a stack rather than joining one. |
measure-count-mismatch.txml | Corresponding lines must agree on measure count across parts. |
measure-number-mismatch.txml | number must match the measure position within its line, counting from 1. |
notated-measure-empty.txml | A measure in a pitched or unpitched part must hold at least one note, rest, or group. An empty one would be a measure of no beats. |
notated-measure-holds-syllable.txml | syllable is valid only in a lyric part. This part is pitched. |
note-pitch-and-sound.txml | pitch and sound are mutually exclusive. A note carries one or the other. |
note-without-pitch-or-sound.txml | A note must carry exactly one of pitch or sound. This one carries neither. |
parenthesis-dim-on-stop.txml | dim and mute describe the whole span, so they are valid only on a parenthesis start. |
parenthesis-span-unclosed.txml | A parenthesis start must be closed by a stop within the same section reference. |
part-data-duplicate-section-ref.txml | A part-data must not reference the same section twice. |
part-data-unresolved.txml | part-data references a part id that no part declares. |
part-stack-without-row.txml | stack and row must appear together. A part with stack must also carry row. |
part-type-invalid.txml | type must be pitched, unpitched, or lyric. |
part-without-part-data.txml | Every part must have exactly one part-data referencing it. P2 has none. |
pitch-double-modifier.txml | A pitch takes at most one Thai octave modifier. This one carries two nikhahit. |
pitch-unknown-letter.txml | pitch="H" is not one of the seven base notes in any of the three spellings. |
play-unresolved.txml | <play> names a section that no <section> declares. |
repeat-times-one.txml | times="1". A repeat that plays its content once is not a repeat, and the default is 2, so a document meaning "play once" writes no <repeat> at all. |
repeat-times-zero.txml | times must be an integer of 1 or greater. |
repeat-without-section.txml | A repeat must contain at least one section, directly or nested. This one wraps only an annotation. |
section-ref-unresolved.txml | section-ref references a section id that no section declares. |
section-ref-without-line.txml | A section-ref must hold at least one line. |
stack-not-adjacent.txml | A stack's parts must be adjacent in ensemble, in ascending row order. Another instrument sits between these two rows. |
stack-row-gap.txml | row values within one stack must run from 1 upward with no gaps. This stack has rows 1 and 3. |
stack-single-part.txml | A stack value must be shared by at least two parts. One part alone is a single-row instrument and carries neither attribute. |
text-align-invalid.txml | align accepts left, center, or right, and nothing else. |
text-duplicate-align.txml | A parent may hold at most one text child per align value. This annotation has two lefts. |
text-with-child-element.txml | text holds text and nothing else. Child elements are invalid. |
wrong-namespace.txml | The root is in a namespace no ThaiMusicXML 1.0 processor implements. |
การใช้ชุดข้อมูล
หัวข้อที่มีชื่อว่า “การใช้ชุดข้อมูล”ชี้การนำไปใช้ของคุณไปที่ทั้งสองไดเรกทอรีและเปรียบเทียบผลลัพธ์กับชื่อไดเรกทอรี นั่นคือทั้งหมด
ตัวตรวจสอบที่ยอมรับทุกอย่างภายใต้ valid/ และปฏิเสธทุกอย่างภายใต้ invalid/ ตรงกับข้อกำหนดนี้ในทุกกฎที่ชุดข้อมูลครอบคลุม ซึ่งคือทุก ต้อง ใน หน้าการสอดคล้องมาตรฐาน ไม่บอกเรื่องการแสดงผล และไม่บอกเรื่องกฎ ควร ที่ตัวประมวลผลควรแจ้งเตือนและทำงานต่อ
เมื่อการอ่านของคุณกับชุดข้อมูลไม่ตรงกัน หนึ่งในสองผิด ควรหาว่าอันไหน เปิด issue แทนที่จะแก้ปัญหาเฉพาะหน้า: กฎที่สองคนอ่านต่างกันคือกฎที่ระบุไม่ดี ชุดข้อมูลมีไว้เพื่อเปิดเผยสิ่งนั้น