A pure-Swift XML parser and serializer with zero dependencies.
Parse XML into an in-memory tree, traverse and manipulate elements, and write it back to well-formed XML — all without Foundation or any third-party libraries.
- Zero dependencies — pure Swift, no Foundation XML classes, no C libraries
- Parse XML from
StringorDatainto a traversable element tree - Write XML back to a string with configurable formatting
- Namespace-aware — default namespaces, prefixed namespaces, undeclaration, shadowing
- Full XML 1.0 support — entities, CDATA, comments, processing instructions, DOCTYPE
- Strict concurrency — all types are
Sendable, built with Swift 6.0 strict concurrency - Builder DSL — construct XML trees declaratively with Swift result builders
- Detailed error reporting — parse errors include line and column numbers
Add XMLKit to your Package.swift:
dependencies: [
.package(url: "https://github.com/steelbrain/XMLKit.git", from: "0.1.0"),
]Then add it as a dependency of your target:
.target(
name: "YourTarget",
dependencies: ["XMLKit"]
),Requirements: Swift 6.0+, macOS 13+ / iOS 16+ / Linux
import XMLKit
let xml = """
<catalog>
<book id="1">
<title>Swift Programming</title>
<author>Apple</author>
</book>
<book id="2">
<title>XML Essentials</title>
</book>
</catalog>
"""
let catalog = try XMLElement.parse(xml)
// Access children by name
let firstBook = catalog.getChild("book")
print(firstBook?.attributes["id"]) // Optional("1")
// Subscript shorthand
let title = catalog["book"]?["title"]?.getText()
print(title) // Optional("Swift Programming")let output = catalog.write()
// <?xml version="1.0" encoding="UTF-8"?>
// <catalog><book id="1"><title>Swift Programming</title>...
// Pretty-printed
let pretty = catalog.write(config: EmitterConfig(performIndent: true))let doc = XMLElement.build("catalog") {
XMLElement.build("book", attributes: ["id": "1"]) {
XMLElement.build("title") { "Swift Programming" }
XMLElement.build("author") { "Apple" }
}
XMLElement.build("book", attributes: ["id": "2"]) {
XMLElement.build("title") { "XML Essentials" }
}
}let xml = """
<root xmlns="urn:books" xmlns:dc="urn:dc">
<dc:title>Example</dc:title>
</root>
"""
let root = try XMLElement.parse(xml)
print(root.namespace) // Optional("urn:books")
let title = root.getChild("title", namespace: "urn:dc")
print(title?.prefix) // Optional("dc")var root = try XMLElement.parse("<root><child name=\"old\"/></root>")
// Mutate a child in place
root.withMutableChild("child") { child in
child.attributes["name"] = "new"
}
// Remove a child
let removed = root.takeChild("child")do {
let elem = try XMLElement.parse("<root><unclosed>")
} catch let error as XMLParseError {
print(error)
// Malformed XML at 1:17: Unexpected end of input inside element <unclosed>
}See API.md for the complete API reference.
See ACKNOWLEDGEMENTS.md.
MIT