The two monolithic XSD content/identity rules only satisfied the OpenAPIKit
validation idiom at the wrong granularity: no per-constraint removability,
no isolable failing/near-miss tests. Split them into 32 named rules, each
finding tagged at its origin and cached per XSDContext so the walk still
runs once per document (the #101 decision against duplicating XSD's
recursive type resolution still holds). Wired the streaming path's ID/IDREF
and identity checks through the same framework instead of calling the
validators imperatively, and added the unwrapAndLookup combinator the rule
already named as required.
Also includes the mandated repo-wide swiftformat/swiftlint pass.
Convert the seven structure-pass compile checkers to located findings so
each error attaches to its own declaring node instead of the schema root
(#169): a facet inapplicable to a list/union variety, a restriction of
xs:anySimpleType and a constraining facet on anySimpleType-based simple
content, a top-level definition missing its name or carrying a local-only
attribute, a nested named definition, an empty targetNamespace or import
namespace, and an all-group reference with an illegal minOccurs/maxOccurs.
The rewire in structureFindings preserves the prior finding order and
count; each error predicate and reason string is unchanged, only the
location each finding carries differs. Adds a located-diagnostics test
per checker family in a new suite kept within the type-body budget.
XSD 1.0 cos-all-limited: a reference to a model group whose content is an
`all` group is itself an all-group particle, so its maxOccurs must be 1 and
its minOccurs 0 or 1. The direct `<all>` element was already checked by
allGroupLimitedErrors, but a `<group ref>` resolving to an all group was not,
so corpus particlesEa025 (`<group ref="x:G" maxOccurs="2">` to an all group)
was accepted.
Add allGroupReferenceMaxOccursErrors: collect the names of group definitions
whose content is an all group, then flag a group reference to one whose
maxOccurs is not 1 or whose minOccurs is not 0/1. The check runs over a single
schema document tree, where group names are unique, so the by-local-name match
cannot collide; a cross-document reference lives in a separate container and is
under-rejected (never falsely rejected).
XSTS invalid-schemas-accepted 36 -> 35; valid-schemas-rejected held at 0.
A complexType nested in an element is a local (anonymous) type definition and
may not carry a name attribute; only a top-level complexType (a child of schema,
or a redefine redefinition) is named. localComplexTypeNameErrors flags a named
complexType whose parent is an element, wired into the structure-walk validation.
XSTS: invalid-schemas-accepted 81 to 80 (ctA042), valid-schemas-rejected held
at 0, no other bucket moved.
An xs:unique / xs:key / xs:keyref content model is (annotation?, selector,
field+): exactly one selector, then one or more fields, in that order. The
structure walk previously checked only that the children were drawn from
{annotation, selector, field}, not their cardinality or order, so a field
before the selector, a second selector, or a missing field was accepted.
identityConstraintContentErrors enforces it, wired into the per-component
structural dispatch. XSTS: invalid-schemas-accepted 110 to 104 (six caught:
idA044/046, idB044/046, idC047/049), valid-schemas-rejected held at 0, no
other bucket moved.
Enforce the two occurrence-range constraints on model groups that PureXML
was not checking:
- p-props-correct.1: a particle's minOccurs may not exceed its maxOccurs,
both defaulting to 1 when the attribute is absent. occurrenceOrderErrors
previously fired only when BOTH attributes were present, so it missed
minOccurs="2" with a defaulted maxOccurs (2 > 1) and maxOccurs="0" with a
defaulted minOccurs (1 > 0). It now orders against the effective defaults.
- cos-all-limited.2: an all group's maxOccurs must be 1 and its minOccurs
0 or 1, and every particle it contains is limited to maxOccurs 0 or 1.
Both are zero-false-positive rules (no valid schema violates them). XSTS:
invalid-schemas-accepted 130 to 110 (20 caught), valid-schemas-rejected
held at 0, no other bucket moved. The differential harness corroborates:
agree-invalid 1751 to 1767, PureXML-stricter unchanged at 87 (no new
over-rejection across 9618 schemas).
A namespace name must be a non-empty anyURI, so <schema targetNamespace=""> and
<import namespace=""> are invalid. Omitting the attribute (no target namespace,
or a no-namespace import) stays valid.
XSTS invalid-schemas-accepted 134 to 132, no other bucket moved.
A referencing attributeGroup (one with a ref) names a definition elsewhere; its
own content model is (annotation?), so it may not also declare attributes,
nested attributeGroup references, or an anyAttribute. Only a defining
attributeGroup (with a name) carries those.
XSTS invalid-schemas-accepted 210 to 207, no other bucket moved.
Two schema-for-schemas structural constraints were not enforced, so the
malformed schemas were accepted:
- The compositor of a top-level named xs:group (all/choice/sequence) may not
carry minOccurs/maxOccurs; those belong on a group reference, not the
definition.
- An attribute in the XML Schema namespace (e.g. xsd:type) is never valid on a
schema element, since the vocabulary defines no namespaced attributes. A
foreign attribute in any other namespace stays the author's own.
XSTS invalid-schemas-accepted 244 to 235, no other bucket moved. (A third
candidate, form on a top-level declaration, was already enforced by the
existing top-level attribute rule, so no new check was needed.)
Cut the second pre-release: schema-validity burn-down to XSTS baselines
1/266/171/155, component child-content shape checks, and synced conformance
docs. CHANGELOG updated for v0.2.0.