diff --git a/Tests/XSTSSuiteTests.swift b/Tests/XSTSSuiteTests.swift index 650c7fb..f1f9060 100644 --- a/Tests/XSTSSuiteTests.swift +++ b/Tests/XSTSSuiteTests.swift @@ -81,7 +81,12 @@ struct XSTSSuiteTests { /// 11 -> 10: anyURI_a004_1339.i reclassified as a contested test, not a bug (see /// the excluded set below). PureXML's acceptance is spec-correct; the suite's /// expectation is internally inconsistent. - private let knownInstanceInvalidAccepted = 10 + /// 10 -> 8: schA2.i and schA5.i reclassified as contested (see the excluded set). + /// Their `invalid` expectation contradicts their own "ignore the inline hint" + /// documentation; under that prescribed behavior both instances are valid. + /// (schA7.i, which looks similar, is NOT excluded: its `invalid` is spec-grounded, + /// a genuine policy-dependent deviation tracked in docs/xsts-deviations.md.) + private let knownInstanceInvalidAccepted = 8 /// Instance tests excluded from the counts because their expected validity is not /// authoritative, mirroring how the suite's own `status="queried"` entries are /// skipped. Each must carry a spec-grounded justification; this is never a place to @@ -102,7 +107,22 @@ struct XSTSSuiteTests { /// non-conformantly fails to compile the schema on the unresolvable include). /// Matching the suite would mean rejecting a valid instance whenever an include /// cannot be resolved, a false positive an IDE editing loop hits constantly. - private static let specDivergentInstances: Set = ["anyURI_a004_1339.i"] + /// + /// - `schA2.i`, `schA5.i`: schema-location precedence. Each group's documentation + /// states the inline `xsi:schemaLocation` hint "is ignored" and the instance + /// "must conform to" the collection schema, but under exactly that prescribed + /// behavior the instances are valid (libxml2 validates schA2.xml against its + /// `a.xsd`, and schA5.xml against its `a.xsd`+`b.xsd` collection), so the + /// `invalid` expectation contradicts the group's own documentation. Reaching + /// `invalid` requires letting the instance's hint override a schema already + /// loaded for that namespace, which XSD 1.0 §4.3.2 makes optional (strategy 1: + /// "do nothing ... because a schema ... is already known") and which would be a + /// direct false positive for an IDE (an instance file forcing rejection against + /// the project's own schema). PureXML's policy (honor hints but keep the + /// collection's declarations on conflict) is conformant. Confirmed by an + /// adversarial analysis that separated these from schA7.i, whose `invalid` IS + /// spec-grounded (a genuine policy deviation, left in the count). + private static let specDivergentInstances: Set = ["anyURI_a004_1339.i", "schA2.i", "schA5.i"] @Test("Every XSTS case behaves: compile, reject, validate, invalidate") func test_suite() throws { diff --git a/docs/xsts-deviations.md b/docs/xsts-deviations.md index 905c4b1..ee24711 100644 --- a/docs/xsts-deviations.md +++ b/docs/xsts-deviations.md @@ -102,6 +102,34 @@ schema on the unresolvable include). Matching the suite would reject a valid instance whenever an include cannot be resolved, a false positive an IDE hits constantly. Recorded in `XSTSSuiteTests.specDivergentInstances`. +The `sch*` schema-location cluster, dissected per case (an adversarial analysis +separated the contested from the genuine): + +- `schA2.i`, `schA5.i`: **contested**, reclassified (`invalid-instances-accepted` + 10 -> 8). Each group's own documentation says the inline `xsi:schemaLocation` + hint "is ignored" and the instance "must conform to" the collection schema; under + exactly that behavior libxml2 validates the instance (schA2 against `a.xsd`, schA5 + against `a.xsd`+`b.xsd`), so the `invalid` expectation contradicts the group's own + documentation. Reaching `invalid` needs the instance's hint to override a schema + already loaded for that namespace, which XSD 1.0 §4.3.2 makes optional (strategy 1) + and which would be a direct IDE false positive. Excluded in `specDivergentInstances`. +- `schA7.i`: **genuine, policy-dependent deviation, left in the count.** Here the + `invalid` IS spec-grounded: with hints ignored, the instance's `b:e1` (namespace + `ns-b`) has no declaration in the `a.xsd`-only collection and is demanded by + `root`'s default-`strict` `##any` wildcard, so §3.10.4 makes it invalid. PureXML + accepts it only by honoring the `ns-b` hint to gap-fill the wildcard, the other + conformant §4.3.2 strategy. A real divergence in schema-location policy, not a + suite bug; not excluded. +- `schU3.i`, `schU4.i`, `schU5.i`: **genuine under-rejection in an underspecified + area, deferred.** These are circular `redefine` chains where one attribute group + (`c-g1`) is redefined to conflicting types (`int` via one document, `string` via + another) across an include/redefine cycle. The suite expects the `int` reading, so + the instance's `c1="a"` is invalid; PureXML resolves to the laxer type and accepts. + libxml2 does not support this at all (it rejects the schema: "Multiple redefinition + of the same component is not supported"), so matching the suite means out-resolving + the reference on a construct whose composition order in a cycle the spec does not + pin down. Tracked as deferred scope, not excluded. + Takeaway: on the schema side, libxml2 parity is reached except the one case now fixed; the remaining nine are a deliberate choice to exceed the reference. On the instance side the Ethiopic-digit `\d`/`\D` and `\i`/`\c` name-class cases are now