Which rules of the specification are enforced¶
XSD is not one rule but 143, each of them named and numbered by the
specification itself: Appendix B of each Recommendation is, in effect, an
index of them. That makes the language a finite checklist rather than a
document you can only read, and this page is that checklist with a column
for what xsdkit does about each entry.
| enforced | rules |
|---|---|
| yes | 89 |
| in part | 31 |
| no | 19 |
| nothing to enforce | 4 |
This is not code coverage, and the difference is the point. Region coverage says how much of what was written gets run; it is silent on a rule nobody wrote. Nor can the W3C suite answer it: the schema half offers only about 220 negative cases per version to share among 66 Schema Component Constraints, so a rule can be entirely absent and cost a percentage point. The table below is the answer to which parts of XSD does this enforce, which is the question a schema author actually has.
A rule marked no is a rule this crate does not check. It is not a bug
report — several are deliberate, and the four nothing to enforce rows
constrain the shape of a component in ways this loader cannot produce — but
it does mean a schema xsdkit accepts is not thereby a valid schema.
The rule columns are generated from the Recommendations
(scripts/extract-spec-rules.py); the judgement columns are maintained by
hand and gated by tests/spec_rules/main.rs, which requires every claim to
name a site and every diagnostic code to be attributable to a row here.
A ✓ in the last column means this crate has its own fixtures for the
rule — the smallest schema that violates it, and a near-miss that must still
load — in tests/spec_rules/fixtures.rs. 12 of 143 rules so far. The W3C
suite cannot supply those: it offers about 220 negative schema cases per
version to share among 66 Schema Component Constraints, so a rule can be
enforced by a check nobody has ever seen fire.
Part 1: Structures¶
92 rules, of which 45 enforced.
Schema Component Constraints¶
| Rule | Enforced | Where, and what is missing | Fixtures |
|---|---|---|---|
| All Group Limited | yes | src/groups.rs — both forms: 1.0 confines an all group and caps its members at one occurrence, 1.1 lifts the cap and allows nesting but requires a referenced group to be an all group |
✓ |
| Annotation Correct | by construction | src/model.rs — property-tableau conformance only; an annotation component cannot be built inconsistent |
|
| Assertion Properties Correct | no | assertions are stored and never evaluated; needs XPath Valid | |
| Attribute Declaration Properties Correct | partial | src/declarations.rs — the value-constraint clause, plus the 1.0 ID rule; the property tableau is satisfied by construction |
|
| Attribute Group Definition Properties Correct | partial | src/compile.rs — clause 1 by construction; clause 2, two uses with one expanded name, is not checked |
|
| Attribute Use Correct | partial | src/declarations.rs — a use's own value constraint is checked as a default; clause 3, a use narrowing a fixed declaration, is not |
|
| Attribute Wildcard Intersection | yes | src/model.rs — attribute wildcard intersection |
|
| Attribute Wildcard Union | yes | src/model.rs — attribute wildcard union |
|
| Complex Type Definition Properties Correct | partial | src/compile.rs — clause 3, no circular definitions, via check_cycles; the simple-base-implies-extension clause is not checked |
|
| Content type restricts (Complex Content) | partial | src/restriction.rs — the judgeable cases; see the module header for what is left unjudged |
|
| Derivation Valid (Extension) | no | Derivation Valid (Extension) is unimplemented as a set rather than half-done (AGENTS.md §7) | |
| Derivation Valid (Restriction, Complex) | partial | src/restriction.rs — Occurrence Range OK, Elt:Elt, Elt:Any, Any:Any, RecurseAsIfGroup, Recurse and RecurseLax; MapAndSum and NSRecurseCheckCardinality are unjudged and accepted |
|
| Derivation Valid (Restriction, Simple) | partial | src/facets.rs — the facet clauses; the variety and base clauses only where the loader can see them |
|
| Effective Total Range (all and sequence) | yes | src/restriction.rs — the effective total range, as the helper Particle Emptiable and the occurrence rules need |
|
| Effective Total Range (choice) | yes | src/restriction.rs — as above, for choice |
|
| Element Declaration Properties Correct | partial | src/declarations.rs — the value-constraint clauses; the substitution-group type clause is not checked |
|
| Element Declarations Consistent | partial | src/instance.rs — the 1.1 dynamic form, reported when a document walks into the clash; the 1.0 static form is not checked |
|
| Element Default Valid (Immediate) | yes | src/declarations.rs — an element's default or fixed against its own type |
|
| Fields Value OK | yes | src/identity.rs — as above, with the attribute step a field may end on |
|
| Identity-constraint Definition Properties Correct | partial | src/load.rs — clause 1 by construction; clause 2, a keyref's field count matching its key's, is not checked |
|
| Model Group Correct | yes | src/compile.rs — clause 2, no circular groups, via check_cycles |
|
| Model Group Definition Properties Correct | by construction | src/load.rs — property-tableau conformance only, and check_representation rejects a definition that is not exactly one model group |
|
| Notation Declaration Correct | by construction | src/model.rs — property-tableau conformance only |
|
| Particle Correct | yes | src/load.rs — minOccurs <= maxOccurs |
|
| Particle Emptiable | yes | src/restriction.rs — a definition rather than a constraint, used by the derivation rules |
|
| Particle Valid (Extension) | partial | src/restriction.rs — a definition used by Derivation Valid (Extension), which is itself unimplemented |
|
| Schema Properties Correct | yes | src/load.rs — clause 2, two components sharing a name in one symbol space |
|
| Selector Value OK | yes | src/identity.rs — the Appendix I subset, parsed and rejected when malformed |
|
| Simple Default Valid | yes | src/declarations.rs — an attribute's default or fixed against its own type |
|
| Simple Type Definition Properties Correct | partial | src/compile.rs — the circularity clause via check_cycles |
|
| Simple Type Restriction (Facets) | yes | src/facets.rs — applicable facets, bounds in the base value space, pairs that cannot hold, and narrowing |
|
| Substitution Group OK (Transitive) | partial | src/compile.rs — the closure honours abstract heads; the type-derivation and disallowed-substitutions clauses are not checked |
|
| Type Alternative Properties Correct | no | conditional type assignment is stored and never evaluated; needs XPath Valid | |
| Type Derivation OK (Complex) | partial | src/derivation.rs — the final clause; used by xsi:type in src/instance.rs |
|
| Type Derivation OK (Simple) | partial | src/derivation.rs — the final clause |
|
| Unique Particle Attribution | yes | src/content.rs — automaton determinism for sequence and choice, and pairwise member overlap for xs:all, which has counters rather than an automaton; a model widened past the position budget reports a warning rather than an error, which only ever over-reports |
✓ |
| Wildcard Properties Correct | partial | src/load.rs — namespace beside notNamespace is rejected; the disallowed-names clause is not checked |
|
| Wildcard Subset | yes | src/restriction.rs — Any:Any NSSubset |
|
| xmlns Not Allowed | no | an attribute declaration named xmlns is accepted | |
| XPath Valid | no | full XPath 2.0, for assertions and CTA; the identity-constraint subset is a different rule | |
| xsi: Not Allowed | no | an attribute declaration in the xsi namespace is accepted |
Schema Representation Constraints¶
| Rule | Enforced | Where, and what is missing | Fixtures |
|---|---|---|---|
| Attribute Declaration Representation OK | partial | src/load.rs — default beside fixed, and ref beside a redescription |
|
| Attribute Group Definition Representation OK | no | nothing checks the representation clauses of an attribute group definition | |
| Complex Type Definition Representation OK | partial | src/load.rs — mixed contradicting itself across xs:complexType and xs:complexContent |
|
| Conditional Inclusion Constraints | yes | src/load.rs — the vc: conditional-inclusion attributes, applied at every descend point |
|
| Element Declaration Representation OK | partial | src/load.rs — default beside fixed, ref beside a redescription, and a local targetNamespace |
|
| Identity-constraint Definition Representation OK | partial | src/load.rs — the ref form against the named form; the selector and field clauses live in src/identity.rs |
|
| Import Constraints and Semantics | partial | src/load.rs — clause 3, the namespace the imported document must declare; clause 1, which forbids importing your own namespace, is not checked |
✓ |
| Inclusion Constraints and Semantics | yes | src/load.rs — clause 2, the namespace the included document may declare, and the chameleon case |
✓ |
| Individual Component Redefinition | partial | src/load.rs — a redefined component must derive from the one it replaces, where the loader can see it |
|
| Override Constraints and Semantics | partial | src/load.rs — the override machinery; not every clause is enforced |
|
| QName resolution (Schema Document) | yes | src/load.rs — a prefixed QName attribute resolved against the document's in-scope bindings |
|
| Redefinition Constraints and Semantics | partial | src/load.rs — the redefinition machinery; not every clause is enforced |
|
| Simple Type Definition Representation OK | yes | src/load.rs — more than one of restriction/list/union on one simple type |
|
| Type Alternative Representation OK | no | type alternatives are read and never checked | |
| Wildcard Representation OK | yes | src/load.rs — namespace beside notNamespace, which names no set |
Validation Rules¶
| Rule | Enforced | Where, and what is missing | Fixtures |
|---|---|---|---|
| Assertion Satisfied | no | assertions are stored and never evaluated | |
| Attribute Locally Valid | yes | src/instance.rs — an attribute's value against its type |
|
| Attribute Locally Valid (Use) | yes | src/instance.rs — required, prohibited and fixed attribute uses |
|
| Element Locally Valid (Complex Type) | yes | src/instance.rs — attributes, content and character data against a complex type |
|
| Element Locally Valid (Element) | yes | src/instance.rs — abstract, xsi:type, the declaration's own value constraint, and xsi:nil against nillable, fixed and content |
✓ |
| Element Locally Valid (Type) | yes | src/instance.rs — abstract types, and the simple-type path into String Valid |
|
| Element Sequence Accepted (Particle) | yes | src/content.rs — whether the sequence reaches an accepting state |
|
| Element Sequence Locally Valid (Complex Content) | yes | src/content.rs — the automaton, xs:all counters and open content |
|
| Element Sequence Locally Valid (Particle) | yes | src/content.rs — one step of the automaton |
|
| Element Sequence Valid | yes | src/content.rs — sequence, choice and all |
|
| Identity-constraint Satisfied | yes | src/identity.rs — xs:key, xs:keyref and xs:unique, matched against the open-element stack |
|
| Item Valid (Wildcard) | yes | src/instance.rs — processContents strict, lax and skip |
|
| QName resolution (Instance) | yes | src/instance.rs — QName and NOTATION values against the instance's namespace stack |
|
| Schema-Validity Assessment (Attribute) | yes | src/instance.rs — assessment of an attribute |
|
| Schema-Validity Assessment (Element) | yes | src/instance.rs — strict, lax and skip assessment of an element |
|
| String Valid | yes | src/validate.rs — a value against a declared simple type, facets composed up the chain |
|
| Validation Root Valid (ID/IDREF) | yes | src/instance.rs — xs:ID uniqueness and xs:IDREF resolution over the validation root |
|
| Wildcard allows Expanded Name | yes | src/content.rs — wildcard_admits, including notQName |
|
| Wildcard allows Namespace Name | yes | src/content.rs — NamespaceConstraint::admits_uri, for names the schema never interned |
|
| XPath Evaluation | no | no XPath engine; needed by assertions and CTA |
Schema Information Set Contributions¶
| Rule | Enforced | Where, and what is missing | Fixtures |
|---|---|---|---|
| Assessment Outcome (Attribute) | partial | src/instance.rs — as above for attributes |
|
| Assessment Outcome (Element) | partial | src/instance.rs — the stream says whether an element was assessed — no declaration means it was not — but there is no per-element validity property; a consumer correlates the diagnostics by line |
|
| Attribute Declaration | yes | src/instance.rs — the governing attribute declaration |
✓ |
| Attribute Default Value | yes | src/instance.rs — a schema-supplied attribute default, flagged from_schema |
✓ |
| Attribute Validated by Type | partial | src/instance.rs — reachable through the attribute declaration; AttributePsvi carries no type id of its own, so an attribute a wildcard admitted with no declaration has none |
|
| Element Declaration | yes | src/instance.rs — the governing element declaration is handed to the consumer |
✓ |
| Element Default Value | yes | src/instance.rs — a schema-supplied element default, flagged from_schema |
✓ |
| Element Validated by Type | yes | src/instance.rs — the type that governed the element, xsi:type included |
✓ |
| ID/IDREF Table | no | src/instance.rs — the ID/IDREF table is enforced and not contributed |
|
| Identity-constraint Table | no | src/identity.rs — the constraints are enforced, but the identity-constraint table is pub(crate) in a private module and never reaches a consumer |
|
| Inherited Attributes | no | inheritable attributes are a 1.1 feature CTA needs; not implemented | |
| Match Information | partial | src/content.rs — the matcher knows whether a declaration or a wildcard matched; it is not surfaced per item |
|
| Schema Information | yes | src/model.rs — Schemas is the schema information, and outlives any one validation |
✓ |
| Validated with Notation | no | a NOTATION value is validated but the notation declaration is not contributed | |
| Validation Failure (Attribute) | partial | src/diagnostics.rs — as above |
|
| Validation Failure (Element) | partial | src/diagnostics.rs — a DiagCode per failure, not yet the Appendix B constraint name |
Part 2: Datatypes¶
51 rules, of which 44 enforced.
Schema Component Constraints¶
| Rule | Enforced | Where, and what is missing | Fixtures |
|---|---|---|---|
| Applicable Facets | yes | src/facets.rs — every declared facet is one the datatype admits |
|
| enumeration facet value required for NOTATION | no | an xs:NOTATION with no enumeration is accepted | |
| enumeration valid restriction | partial | src/facets.rs — literals are checked against the base's built-in ancestor, not against the base's own facets |
|
| fractionDigits less than or equal to totalDigits | yes | src/facets.rs — fractionDigits may not exceed totalDigits |
|
| fractionDigits valid restriction | yes | src/facets.rs — narrowing check |
|
| length and minLength or maxLength | yes | src/facets.rs — length beside minLength or maxLength |
|
| length valid restriction | yes | src/facets.rs — narrowing check |
|
| maxExclusive valid restriction | yes | src/facets.rs — narrowing check |
|
| maxInclusive and maxExclusive | yes | src/load.rs — both bounds at one step |
|
| maxInclusive valid restriction | yes | src/facets.rs — narrowing check |
|
| maxLength valid restriction | yes | src/facets.rs — narrowing check |
|
| minExclusive < maxInclusive | yes | src/load.rs — the pair check |
|
| minExclusive <= maxExclusive | yes | src/load.rs — the pair check |
|
| minExclusive valid restriction | yes | src/facets.rs — narrowing check |
|
| minInclusive < maxExclusive | yes | src/load.rs — the pair check |
|
| minInclusive <= maxInclusive | yes | src/load.rs — the pair check |
|
| minInclusive and minExclusive | yes | src/load.rs — both bounds at one step |
|
| minInclusive valid restriction | yes | src/facets.rs — narrowing check |
|
| minLength <= maxLength | yes | src/facets.rs — the pair check |
|
| minLength valid restriction | yes | src/facets.rs — narrowing check |
|
| timezone valid restriction | no | src/values.rs — the facet is enforced against values; narrowing it across a restriction step is not checked |
|
| totalDigits valid restriction | yes | src/facets.rs — narrowing check |
|
| Valid restriction of assertions | no | assertions are not evaluated, so a restriction of them is not checked | |
| Valid restriction of pattern | by construction | src/validate.rs — patterns intersect down the chain, so a step can only narrow |
|
| whiteSpace valid restriction | no | a step may widen whiteSpace from collapse back to preserve |
Schema Representation Constraints¶
| Rule | Enforced | Where, and what is missing | Fixtures |
|---|---|---|---|
| base attribute or simpleType child | yes | src/load.rs — base beside an inline simpleType |
|
| Enumeration value | yes | src/facets.rs — each enumerated literal is a value of the base |
|
| itemType attribute or simpleType child | yes | src/load.rs — itemType beside an inline simpleType |
|
| memberTypes attribute or simpleType children | yes | src/load.rs — memberTypes beside inline simpleTypes |
|
| Pattern value | yes | src/regex.rs, src/facets.rs — the pattern translates as an XSD regular expression, and one that does not is reported where it is declared; an unknown block name is a warning and matches every character, as XSD 1.1 G.4.2.4 prescribes |
✓ |
Validation Rules¶
| Rule | Enforced | Where, and what is missing | Fixtures |
|---|---|---|---|
| Assertions Valid | no | assertions are not evaluated | |
| Datatype Valid | yes | src/validate.rs — atomic, list and union varieties |
|
| enumeration valid | yes | src/values.rs — compared in the value space, not as strings |
|
| explicitOffset Valid | yes | src/values.rs — required, prohibited and optional against a value's timezone |
|
| Facet Valid | yes | src/values.rs — check_facets, against the set src/validate.rs composed up the chain |
|
| fractionDigits Valid | yes | src/values.rs |
|
| Length Valid | yes | src/values.rs — facet_length, which each datatype defines for itself |
|
| maxExclusive Valid | yes | src/values.rs |
|
| maxInclusive Valid | yes | src/values.rs |
|
| maxLength Valid | yes | src/values.rs |
|
| minExclusive Valid | yes | src/values.rs |
|
| minInclusive Valid | yes | src/values.rs |
|
| minLength Valid | yes | src/values.rs |
|
| pattern valid | yes | src/regex.rs — XSD regular expressions, compiled and matched |
|
| totalDigits Valid | yes | src/values.rs |
Constraints¶
| Rule | Enforced | Where, and what is missing | Fixtures |
|---|---|---|---|
| Day-of-month Representations | yes | src/atomic.rs — as above for xs:date |
|
| Day-of-month Representations | yes | src/atomic.rs — the lexical form is rejected with it |
|
| Day-of-month Representations | yes | src/atomic.rs — as above for xs:gMonthDay |
|
| Day-of-month Values | yes | src/atomic.rs — as above for xs:date |
|
| Day-of-month Values | yes | src/atomic.rs — a day that does not exist in its month is not a value |
|
| Day-of-month Values | yes | src/atomic.rs — as above for xs:gMonthDay, which is why --02-29 is a value |