PureXML/Tests/SchemaMultiDocumentTests.swift
Mihaela Mihaljevic 092e9a488d feat(schema): honor instance xsi:schemaLocation for multi-document validation
A strict or lax wildcard must resolve elements declared in schema documents an
instance points at through xsi:schemaLocation, which the main schema need not
import. validate(_:schemaLoader:) now reads the instance's xsi:schemaLocation
and xsi:noNamespaceSchemaLocation hints, loads and compiles each referenced
document through the loader, and merges its global declarations in (the primary
schema wins on conflict). The plain validate(_:) is unchanged; the XSTS runner
resolves hints relative to the instance file.

XSTS: valid instances rejected 308 to 288 (the particle clusters whose
wildcard-matched elements live in a separate, instance-referenced schema).
Baseline updated; regression tests cover cross-document resolution, the loaded
type being enforced, and strict failure without the loader.

Refs #147, #129.
2026-06-13 19:54:12 +02:00

55 lines
2.2 KiB
Swift

@testable import PureXML
import Testing
/// `validate(_:schemaLoader:)` honors an instance's `xsi:schemaLocation`,
/// loading the referenced schema documents so a strict (or lax) wildcard can
/// resolve elements declared in another document (#147, XSTS particles set).
@Suite("Multi-document validation via xsi:schemaLocation")
struct SchemaMultiDocumentTests {
private let mainXSD = """
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:a" xmlns:a="urn:a">
<xs:element name="doc">
<xs:complexType>
<xs:sequence>
<xs:any namespace="##other" processContents="strict" minOccurs="1" maxOccurs="3"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
"""
private let otherXSD = """
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:b">
<xs:element name="thing" type="xs:int"/>
</xs:schema>
"""
private let instance = """
<a:doc xmlns:a="urn:a" xmlns:b="urn:b"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:b other.xsd"><b:thing>5</b:thing></a:doc>
"""
@Test("A strict wildcard resolves an element from the xsi:schemaLocation schema")
func test_resolvesAcrossDocuments() throws {
let doc = try PureXML.Schema.Document(mainXSD)
let loader: (String) -> String? = { [otherXSD] in $0 == "other.xsd" ? otherXSD : nil }
#expect(try doc.validate(instance, schemaLoader: loader).isEmpty)
}
@Test("The loaded declaration's type is still enforced")
func test_loadedTypeEnforced() throws {
let doc = try PureXML.Schema.Document(mainXSD)
let loader: (String) -> String? = { [otherXSD] in $0 == "other.xsd" ? otherXSD : nil }
let bad = instance.replacingOccurrences(of: "<b:thing>5</b:thing>", with: "<b:thing>notint</b:thing>")
#expect(try !doc.validate(bad, schemaLoader: loader).isEmpty)
}
@Test("Without the loader a strict wildcard cannot resolve the element")
func test_strictUnresolvedWithoutLoader() throws {
let doc = try PureXML.Schema.Document(mainXSD)
#expect(try !doc.validate(instance).isEmpty)
}
}