Работа с XML в Swift (iOS/macOS): полное руководство
XML (eXtensible Markup Language) остаётся востребованным форматом для обмена данными, конфигурационных файлов и веб-сервисов. В экосистеме Apple для работы с XML в Swift доступны как встроенные средства Foundation (класс XMLParser), так и сторонние библиотеки, например SwiftXML. В этой статье мы подробно разберём оба подхода с примерами кода для iOS и macOS.
1. Встроенный XMLParser из Foundation
XMLParser — это SAX-парсер (последовательный, событийно-ориентированный). Он не загружает весь документ в память, а разбирает его по мере чтения, вызывая методы делегата. Это идеально для больших XML-файлов.
1.1. Базовая настройка и делегат
Создайте класс, реализующий протокол XMLParserDelegate. Обязательные методы:
parser(_:didStartElement:namespaceURI:qualifiedName:attributes:)— вызывается при открытии тега.parser(_:foundCharacters:)— получает текстовое содержимое элемента.parser(_:didEndElement:namespaceURI:qualifiedName:)— вызывается при закрытии тега.
import Foundation
class XMLHandler: NSObject, XMLParserDelegate {
var currentElement = ""
var currentText = ""
func parser(_ parser: XMLParser,
didStartElement elementName: String,
namespaceURI: String?,
qualifiedName qName: String?,
attributes attributeDict: [String : String] = [:]) {
currentElement = elementName
currentText = ""
if elementName == "book" {
print("Начало книги: \(attributeDict["id"] ?? "")")
}
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
currentText += string
}
func parser(_ parser: XMLParser,
didEndElement elementName: String,
namespaceURI: String?,
qualifiedName qName: String?) {
if elementName == "title" {
print("Название: \(currentText.trimmingCharacters(in: .whitespacesAndNewlines))")
}
}
}
// Использование
if let url = Bundle.main.url(forResource: "books", withExtension: "xml"),
let parser = XMLParser(contentsOf: url) {
let handler = XMLHandler()
parser.delegate = handler
parser.parse()
}
1.2. Обработка ошибок и пространства имён
Реализуйте метод parser(_:parseErrorOccurred:) для логирования ошибок. Для работы с пространствами имён используйте параметры namespaceURI и qualifiedName.
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
print("Ошибка парсинга: \(parseError.localizedDescription)")
}
2. Создание XML-документов вручную
Для генерации XML в Swift можно использовать строки или библиотеку XMLDocument из Foundation (доступна только на macOS). На iOS придётся создавать XML вручную.
2.1. Генерация XML через строки (iOS/macOS)
func createXMLString() -> String {
var xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
xml += "<library>\n"
xml += " <book id=\"1\">\n"
xml += " <title>Swift Programming</title>\n"
xml += " <author>Apple Inc.</author>\n"
xml += " </book>\n"
xml += "</library>\n"
return xml
}
let xmlString = createXMLString()
print(xmlString)
2.2. Использование XMLDocument (macOS только)
import Foundation
let root = XMLElement(name: "library")
let book = XMLElement(name: "book")
book.addAttribute(XMLNode.attribute(withName: "id", stringValue: "1") as! XMLNode)
let title = XMLElement(name: "title", stringValue: "Swift Programming")
let author = XMLElement(name: "author", stringValue: "Apple Inc.")
book.addChild(title)
book.addChild(author)
root.addChild(book)
let document = XMLDocument(rootElement: root)
document.version = "1.0"
document.characterEncoding = "UTF-8"
let data = document.xmlData(options: .nodePrettyPrint)
if let xmlString = String(data: data, encoding: .utf8) {
print(xmlString)
}
3. Библиотека SwiftXML
SwiftXML — современная библиотека с открытым исходным кодом, которая предоставляет DOM-подобный API (документ загружается в память целиком). Поддерживает XPath, пространства имён и преобразование в JSON.
3.1. Установка через Swift Package Manager
// Package.swift
dependencies: [
.package(url: "https://github.com/Sw