import Testing @testable import PureXML @Suite("Namespaces") struct NamespaceTests { @Test("Default namespace applies to the element and inherits to children") func test_defaultNamespace() throws { let root = try rootElement("") #expect(root.name.namespaceURI == "http://x") #expect(firstChildElement(root)?.name.namespaceURI == "http://x") } @Test("Prefixed element and attribute names resolve to their URI") func test_prefixedResolution() throws { let root = try rootElement("") #expect(root.name.namespaceURI == nil) let prefixed = root.attributes.first { $0.name.localName == "x" } #expect(prefixed?.name.namespaceURI == "http://p") #expect(firstChildElement(root)?.name.namespaceURI == "http://p") } @Test("Default namespace does not apply to unprefixed attributes") func test_defaultNamespaceSkipsAttributes() throws { let root = try rootElement("") #expect(root.name.namespaceURI == "http://x") let identifier = root.attributes.first { $0.name.localName == "id" } #expect(identifier?.name.namespaceURI == nil) } @Test("The xml prefix is bound to the reserved namespace") func test_xmlPrefixReserved() throws { let root = try rootElement("") let lang = root.attributes.first { $0.name.localName == "lang" } #expect(lang?.name.namespaceURI == PureXML.Parsing.NamespaceContext.xmlNamespaceURI) } @Test("An unbound prefix is rejected") func test_unboundPrefixRejected() { #expect(throws: PureXML.Parsing.ParseError.self) { try PureXML.parse("") } } @Test("xmlns declarations are preserved as attributes for round-trip") func test_xmlnsDeclarationPreserved() throws { let root = try rootElement("") #expect(root.attributes.contains { $0.name.description == "xmlns:p" }) } @Test("A redeclared default namespace is scoped and reverts") func test_scopedRedeclaration() throws { let root = try rootElement("") #expect(root.name.namespaceURI == "http://1") let children = root.children.compactMap { node -> PureXML.Model.Element? in if case let .element(element) = node { return element } return nil } #expect(children.first?.name.namespaceURI == "http://2") #expect(children.last?.name.namespaceURI == "http://1") } private func rootElement(_ xml: String) throws -> PureXML.Model.Element { let node = try PureXML.parse(xml) guard case let .document(children) = node else { throw Failure.notDocument } for child in children { if case let .element(element) = child { return element } } throw Failure.noElement } private func firstChildElement(_ element: PureXML.Model.Element) -> PureXML.Model.Element? { for child in element.children { if case let .element(found) = child { return found } } return nil } private enum Failure: Error { case notDocument, noElement } }