<sch:rule context="mei:staffDef[not(ancestor::mei:staff)]">
<sch:let name="thisstaff" value="@n"/>
<sch:assert test="@n">StaffDef must have an n attribute.</sch:assert>
<sch:assert test="@lines or preceding::mei:staffDef[@n=$thisstaff and @lines]"> Either
@lines must be present or a preceding staffDef with the same value for @n and @lines
must exist.</sch:assert>
<sch:assert test="count(mei:clef) + count(mei:clefGrp) < 2">Only one clef or clefGrp is
permitted.</sch:assert>
</sch:rule>
<sch:rule context="mei:staffDef[ancestor::mei:staff and @n]">
<sch:let name="thisstaff" value="@n"/>
<sch:assert test="ancestor::mei:staff/@n eq $thisstaff">@n must have the same value as the
current staff.</sch:assert>
</sch:rule>
<sch:rule context="mei:staffDef[ancestor::mei:staff and not(@n)]">
<sch:let name="thisstaff" value="ancestor::mei:staff/@n"/>
<sch:assert test="@lines or preceding::mei:staffDef[@n=$thisstaff and @lines]"> Either
@lines must be present or a preceding staffDef with matching @n value and @lines must
exist.</sch:assert>
</sch:rule>
<sch:rule context="mei:staffDef[@clef.line and @lines]">
<sch:assert test="number(@clef.line) <= number(@lines)">The clef position must be less
than or equal to the number of lines on the staff.</sch:assert>
</sch:rule>
<sch:rule context="mei:staffDef[@clef.line and not(@lines)]">
<sch:let name="thisstaff" value="@n"/>
<sch:let name="stafflines" value="preceding::mei:staffDef[@n=$thisstaff and @lines][1]/@lines"/>
<sch:assert test="number(@clef.line) <= number($stafflines)">The clef position must be
less than or equal to the number of lines on the staff.</sch:assert>
</sch:rule>
<sch:rule context="mei:staffDef[@tab.strings and @lines]">
<sch:let name="countTokens" value="count(tokenize(normalize-space(@tab.strings), '\s'))"/>
<sch:assert test="$countTokens = @lines">The tab.strings attribute must have the same
number of values as there are staff lines.</sch:assert>
</sch:rule>
<sch:rule context="mei:staffDef[@tab.strings and not(@lines)]">
<sch:let name="countTokens" value="count(tokenize(normalize-space(@tab.strings), '\s'))"/>
<sch:let name="thisstaff" value="@n"/>
<sch:assert test="$countTokens = preceding::mei:staffDef[@n=$thisstaff and @lines][1]/@lines">The
tab.strings attribute must have the same number of values as there are staff
lines.</sch:assert>
</sch:rule>
<sch:rule context="mei:staffDef[@lines.color and @lines]">
<sch:let name="countTokens" value="count(tokenize(normalize-space(@lines.color), '\s'))"/>
<sch:assert test="$countTokens = 1 or $countTokens = @lines">The lines.color attribute
must have either 1) a single value or 2) the same number of values as there are staff
lines.</sch:assert>
</sch:rule>
<sch:rule context="mei:staffDef[@lines.color and not(@lines)]">
<sch:let name="countTokens" value="count(tokenize(normalize-space(@lines.color), '\s'))"/>
<sch:let name="thisstaff" value="@n"/>
<sch:assert test="$countTokens = 1 or $countTokens = preceding::mei:staffDef[@n=$thisstaff and @lines][1]/@lines">The lines.color attribute must have either 1) a single value or 2) the same number
of
values as there are staff lines.</sch:assert>
</sch:rule>
<sch:rule context="mei:staffDef[@ppq][ancestor::mei:scoreDef[@ppq]]">
<sch:let name="staffPPQ" value="@ppq"/>
<sch:let name="scorePPQ" value="ancestor::mei:scoreDef[@ppq][1]/@ppq"/>
<sch:assert test="($scorePPQ mod $staffPPQ) = 0">The value of ppq must be a factor of
the value of ppq on an ancestor scoreDef.</sch:assert>
</sch:rule>
<sch:rule context="mei:staffDef[@ppq][preceding::mei:scoreDef[@ppq]]">
<sch:let name="staffPPQ" value="@ppq"/>
<sch:let name="scorePPQ" value="preceding::mei:scoreDef[@ppq][1]/@ppq"/>
<sch:assert test="($scorePPQ mod $staffPPQ) = 0">The value of ppq must be a factor of
the value of ppq on a preceding scoreDef.</sch:assert>
</sch:rule>
<elementSpec ident="staffDef" module="MEI.shared">
<desc>(staff definition) – Container for staff meta-information.</desc>
<classes>
<memberOf
key="att.basic"/>
<memberOf
key="att.labelled"/>
<memberOf
key="att.linking"/>
<memberOf
key="att.metadataPointing"/>
<memberOf
key="att.nInteger"/>
<memberOf
key="att.responsibility"/>
<memberOf
key="att.typed"/>
<memberOf
key="att.staffDef.log"/>
<memberOf
key="att.staffDef.vis"/>
<memberOf
key="att.staffDef.ges"/>
<memberOf
key="att.staffDef.anl"/>
<memberOf
key="model.staffDefLike"/>
</classes>
<content>
<rng:zeroOrMore>
<rng:choice>
<rng:ref
name="model.instrDefLike"
/>
<rng:ref
name="model.layerDefLike"
/>
<rng:ref
name="model.staffDefPart"
/>
</rng:choice>
</rng:zeroOrMore>
</content>
<constraintSpec ident="Check_staffDefn" scheme="isoschematron">
<constraint>
<sch:rule context="mei:staffDef[not(ancestor::mei:staff)]">
<sch:let name="thisstaff" value="@n"/>
<sch:assert test="@n">StaffDef must have an n attribute.</sch:assert>
<sch:assert test="@lines or preceding::mei:staffDef[@n=$thisstaff and @lines]"> Either
@lines must be present or a preceding staffDef with the same value for @n and @lines
must exist.</sch:assert>
<sch:assert test="count(mei:clef) + count(mei:clefGrp) < 2">Only one clef or clefGrp is
permitted.</sch:assert>
</sch:rule>
</constraint>
</constraintSpec>
<constraintSpec ident="Check_ancestor_staff" scheme="isoschematron">
<constraint>
<sch:rule context="mei:staffDef[ancestor::mei:staff and @n]">
<sch:let name="thisstaff" value="@n"/>
<sch:assert test="ancestor::mei:staff/@n eq $thisstaff">@n must have the same value as the
current staff.</sch:assert>
</sch:rule>
</constraint>
</constraintSpec>
<constraintSpec ident="Check_ancestor_staff_lines" scheme="isoschematron">
<constraint>
<sch:rule context="mei:staffDef[ancestor::mei:staff and not(@n)]">
<sch:let name="thisstaff" value="ancestor::mei:staff/@n"/>
<sch:assert test="@lines or preceding::mei:staffDef[@n=$thisstaff and @lines]"> Either
@lines must be present or a preceding staffDef with matching @n value and @lines must
exist.</sch:assert>
</sch:rule>
</constraint>
</constraintSpec>
<constraintSpec ident="Check_clef_position_staffDef" scheme="isoschematron">
<constraint>
<sch:rule context="mei:staffDef[@clef.line and @lines]">
<sch:assert test="number(@clef.line) <= number(@lines)">The clef position must be less
than or equal to the number of lines on the staff.</sch:assert>
</sch:rule>
</constraint>
</constraintSpec>
<constraintSpec ident="Check_clef_position_staffDef_nolines" scheme="isoschematron">
<constraint>
<sch:rule context="mei:staffDef[@clef.line and not(@lines)]">
<sch:let name="thisstaff" value="@n"/>
<sch:let name="stafflines" value="preceding::mei:staffDef[@n=$thisstaff and @lines][1]/@lines"/>
<sch:assert test="number(@clef.line) <= number($stafflines)">The clef position must be
less than or equal to the number of lines on the staff.</sch:assert>
</sch:rule>
</constraint>
</constraintSpec>
<constraintSpec ident="Check_tab_strings_lines" scheme="isoschematron">
<constraint>
<sch:rule context="mei:staffDef[@tab.strings and @lines]">
<sch:let name="countTokens" value="count(tokenize(normalize-space(@tab.strings), '\s'))"/>
<sch:assert test="$countTokens = @lines">The tab.strings attribute must have the same
number of values as there are staff lines.</sch:assert>
</sch:rule>
</constraint>
</constraintSpec>
<constraintSpec ident="Check_tab_strings_nolines" scheme="isoschematron">
<constraint>
<sch:rule context="mei:staffDef[@tab.strings and not(@lines)]">
<sch:let name="countTokens" value="count(tokenize(normalize-space(@tab.strings), '\s'))"/>
<sch:let name="thisstaff" value="@n"/>
<sch:assert test="$countTokens = preceding::mei:staffDef[@n=$thisstaff and @lines][1]/@lines">The
tab.strings attribute must have the same number of values as there are staff
lines.</sch:assert>
</sch:rule>
</constraint>
</constraintSpec>
<constraintSpec ident="Check_lines_color" scheme="isoschematron">
<constraint>
<sch:pattern>
<sch:rule context="mei:staffDef[@lines.color and @lines]">
<sch:let name="countTokens" value="count(tokenize(normalize-space(@lines.color), '\s'))"/>
<sch:assert test="$countTokens = 1 or $countTokens = @lines">The lines.color attribute
must have either 1) a single value or 2) the same number of values as there are staff
lines.</sch:assert>
</sch:rule>
<sch:rule context="mei:staffDef[@lines.color and not(@lines)]">
<sch:let name="countTokens" value="count(tokenize(normalize-space(@lines.color), '\s'))"/>
<sch:let name="thisstaff" value="@n"/>
<sch:assert test="$countTokens = 1 or $countTokens = preceding::mei:staffDef[@n=$thisstaff and @lines][1]/@lines">The lines.color attribute must have either 1) a single value or 2) the same number
of
values as there are staff lines.</sch:assert>
</sch:rule>
</sch:pattern>
</constraint>
</constraintSpec>
<constraintSpec ident="Check_staff_ppq_ancestor" scheme="isoschematron">
<constraint>
<sch:pattern>
<sch:rule context="mei:staffDef[@ppq][ancestor::mei:scoreDef[@ppq]]">
<sch:let name="staffPPQ" value="@ppq"/>
<sch:let name="scorePPQ" value="ancestor::mei:scoreDef[@ppq][1]/@ppq"/>
<sch:assert test="($scorePPQ mod $staffPPQ) = 0">The value of ppq must be a factor of
the value of ppq on an ancestor scoreDef.</sch:assert>
</sch:rule>
</sch:pattern>
</constraint>
</constraintSpec>
<constraintSpec ident="Check_staff_ppq_preceding" scheme="isoschematron">
<constraint>
<sch:pattern>
<sch:rule context="mei:staffDef[@ppq][preceding::mei:scoreDef[@ppq]]">
<sch:let name="staffPPQ" value="@ppq"/>
<sch:let name="scorePPQ" value="preceding::mei:scoreDef[@ppq][1]/@ppq"/>
<sch:assert test="($scorePPQ mod $staffPPQ) = 0">The value of ppq must be a factor of
the value of ppq on a preceding scoreDef.</sch:assert>
</sch:rule>
</sch:pattern>
</constraint>
</constraintSpec>
</elementSpec>