PureXML/Tests/SchemaLocalElementBlockKeyTests.swift
Mihaela Mihaljevic c3393bcaad fix(schema): key a local element's block by its effective instance namespace; invalid-instances-accepted 32 to 31 (#147)
The namespaced derivation backbone keyed every element by the container target
namespace, but a local element is in the target namespace only when qualified (its
own form, else the schema's elementFormDefault). An unqualified local element's
block was keyed {targetNS}name while the instance element is {}name, so
blockedSubstitutionError's lookup missed and a blocked xsi:type substitution on it
was accepted (typeDef00801: a local Element with block="extension" did not bar an
extension substitution).

gatherElement now keys a local element by localElementNamespace (target namespace
when qualified, none otherwise); global elements stay keyed by the target
namespace, and the bare-keyed tables are unchanged.

invalid-instances-accepted 32 to 31, no false positive (valid-instances-rejected
and valid-schemas-rejected held at 0). An adversarial review confirmed qualified
local elements are unchanged, global and same-named local element keys stay
distinct, and a non-blocked substitution on a local element is still accepted.
2026-06-18 16:12:08 +02:00

28 lines
1.6 KiB
Swift

@testable import PureXML
import Testing
/// A `block` on a LOCAL element declaration applies to that element by its instance
/// (qualified) name. When the schema is unqualified (no elementFormDefault), the
/// local element is in no namespace, so the block must be keyed there for an
/// xsi:type substitution on it to be barred (W3C sun typeDef00801).
@Suite("local element block keying")
struct SchemaLocalElementBlockKeyTests {
@Test("block on an unqualified local element bars an xsi:type extension")
func test_unqualifiedLocalElementBlock() throws {
let schema = try PureXML.Schema.Document("""
<xsd:schema xmlns="u" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="u">
<xsd:element name="root"><xsd:complexType><xsd:sequence>
<xsd:element name="Element" type="Type" block="extension"/>
</xsd:sequence></xsd:complexType></xsd:element>
<xsd:complexType name="Type"><xsd:attribute name="value" type="xsd:boolean"/></xsd:complexType>
<xsd:complexType name="derivedType"><xsd:complexContent>
<xsd:extension base="Type"><xsd:attribute name="value1" type="xsd:boolean"/></xsd:extension>
</xsd:complexContent></xsd:complexType>
</xsd:schema>
""")
// Element is unqualified (no elementFormDefault): in instance it is in no namespace.
let doc = #"<test:root xmlns:test="u" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Element xsi:type="test:derivedType" value="false" value1="true"/></test:root>"#
#expect(try !schema.validate(doc).isEmpty)
}
}