NameAndTypeOK clause 1 (XSD 1.0 section 3.9.6, Elt:Elt) pairs the declared
element declarations and requires the same {name} and {target namespace};
no clause grants substitution an allowance. The substitution-group
expansion rewrites the compiled term (an abstract head is dropped, members
join a synthetic choice), so the checker previously compared the expanded
names and a head-for-member swap looked name-identical.
Particle.declaredReference now preserves the pre-expansion identity of an
element-ref particle, and the restriction check pairs the declared
references before the structural pairing table (extracted as
structuralValid). Closes XSTS elemZ026 and particlesV020:
invalid-schemas-accepted 8 -> 6, valid buckets unchanged at zero.
Stricter than libxml2, which does not implement this edge; elemZ026 is
pinned in the differential baseline accordingly.
particlesZ008, byte-for-byte the same construct as elemZ026 but carrying
a settled valid expectation contradicting elemZ026's settled invalid, is
reclassified as a spec-divergent schema test with the adjudication
recorded in the suite (exclusion tables split into
Tests/XSTSSuiteExclusions.swift for file length).
Separately attributed: the differential baseline gains ten further pinned
entries (addB070a, addB108, addB177, attO025, elemZ027_c, errC008,
groupH021v, notatB005, notatE002, particlesEb040) that reproduce with
this change stashed. They are pre-existing drift from earlier main-line
fixes, not effects of this commit. Baseline 231 -> 242, differential
green.
62 lines
2.8 KiB
Swift
62 lines
2.8 KiB
Swift
import Testing
|
|
@testable import PureXML
|
|
|
|
@Suite("XSD Particle Restriction over substitution groups")
|
|
struct XSDParticleSubstitutionRestrictionTests {
|
|
private let xsNamespace = "xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
|
|
|
|
@Test("A restriction may not swap an element ref for a substitution-group member")
|
|
func test_substitutionMemberSwapRejected() {
|
|
// elemZ026: NameAndTypeOK clause 1 pairs the DECLARED references, and requires
|
|
// the same name and target namespace; substitution has no allowance in Elt:Elt.
|
|
// Swapping the head ref for a member ref names a different declaration.
|
|
let schema = """
|
|
<xs:schema \(xsNamespace)>
|
|
<xs:complexType name="headType" abstract="true">
|
|
<xs:sequence><xs:element name="leaf" type="xs:token"/></xs:sequence>
|
|
</xs:complexType>
|
|
<xs:element name="head" type="headType" abstract="true"/>
|
|
<xs:element name="member" type="headType" substitutionGroup="head"/>
|
|
<xs:complexType name="B">
|
|
<xs:sequence><xs:element ref="head" maxOccurs="unbounded"/></xs:sequence>
|
|
</xs:complexType>
|
|
<xs:complexType name="R">
|
|
<xs:complexContent><xs:restriction base="B">
|
|
<xs:sequence><xs:element ref="member" maxOccurs="unbounded"/></xs:sequence>
|
|
</xs:restriction></xs:complexContent>
|
|
</xs:complexType>
|
|
<xs:element name="r" type="R"/>
|
|
</xs:schema>
|
|
"""
|
|
#expect(throws: (any Error).self) {
|
|
try PureXML.Schema.Document(schema)
|
|
}
|
|
}
|
|
|
|
@Test("A restriction that repeats the declared ref and narrows occurrence compiles")
|
|
func test_sameRefNarrowedOccurrenceCompiles() throws {
|
|
// The positive control for the declared-reference check: the same head ref with
|
|
// a narrowed range is the spec's idiom, and the substitution expansion behind
|
|
// both sides must not disturb it.
|
|
let schema = """
|
|
<xs:schema \(xsNamespace)>
|
|
<xs:complexType name="headType" abstract="true">
|
|
<xs:sequence><xs:element name="leaf" type="xs:token"/></xs:sequence>
|
|
</xs:complexType>
|
|
<xs:element name="head" type="headType" abstract="true"/>
|
|
<xs:element name="member" type="headType" substitutionGroup="head"/>
|
|
<xs:complexType name="B">
|
|
<xs:sequence><xs:element ref="head" minOccurs="0" maxOccurs="unbounded"/></xs:sequence>
|
|
</xs:complexType>
|
|
<xs:complexType name="R">
|
|
<xs:complexContent><xs:restriction base="B">
|
|
<xs:sequence><xs:element ref="head" maxOccurs="2"/></xs:sequence>
|
|
</xs:restriction></xs:complexContent>
|
|
</xs:complexType>
|
|
<xs:element name="r" type="R"/>
|
|
</xs:schema>
|
|
"""
|
|
_ = try PureXML.Schema.Document(schema)
|
|
}
|
|
}
|