在 Swift 中处理 XML:数据解析、创建与处理(iOS/macOS)

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

在 Swift 中处理 XML(iOS/macOS):从解析到创建



XML(可扩展标记语言)仍被用于遗留系统、Web 服务(SOAP、RSS)和配置文件中。在 iOS/macOS 的 Swift 中,虽然没有内置的语法糖库,但有一个强大的 XMLParser(SAX 解析器),以及流行的第三方库 AEXML(DOM 方式)。本文将介绍这两种方法。



1. 内置 XMLParser(SAX 方式)



XMLParser 是 Foundation 中基于事件驱动(SAX)的解析器。它不会将整个文档加载到内存中,而是在遇到元素时调用委托方法。非常适合处理大文件。



示例:解析 RSS 订阅源



import Foundation

class RSSParser: NSObject, XMLParserDelegate { private var currentElement = "" private var currentTitle = "" private var items: [String] = []

func parse(data: Data) -> [String] { let parser = XMLParser(data: data) parser.delegate = self parser.parse() return items }

// MARK: - XMLParserDelegate func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { currentElement = elementName if elementName == "item" { currentTitle = "" } }

func parser(_ parser: XMLParser, foundCharacters string: String) { if currentElement == "title" { currentTitle += string } }

func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { if elementName == "title" && !currentTitle.isEmpty { items.append(currentTitle.trimmingCharacters(in: .whitespacesAndNewlines)) } }}

// 使用示例let xmlString = """<rss> <channel> <item><title>Swift 6.0</title></item> <item><title>Xcode 新功能</title></item> </channel></rss>"""if let data = xmlString.data(using: .utf8) { let parser = RSSParser() let titles = parser.parse(data: data) print(titles) // ["Swift 6.0", "Xcode 新功能"]}


重要提示: foundCharacters 可能会为同一个文本节点被多次调用(尤其是包含西里尔字母时)。请始终累积字符串,而不是直接赋值。



2. AEXML — 便捷的 DOM 库



AEXML 是一个轻量级的 DOM 风格 XML 处理库。无需手动管理事件即可读取和创建 XML。可通过 Swift Package Manager 或 CocoaPods 安装。



通过 Swift Package Manager 安装

在 Package.swift 或通过 Xcode 添加:File → Add Packages → 输入 URL:https://github.com/tadija/AEXML.git



示例:读取 XML



import AEXML

func parseWithAEXML(xmlString: String) -> [String: String]? { do { let xmlDoc = try AEXMLDocument(xml: xmlString) let root = xmlDoc.root

// 获取元素的值 let name = root["user"]["name"].value ?? "" let age = root["user"]["age"].value ?? ""

// 通过属性访问 let id = root["user"].attributes["id"] ?? ""

return ["id": id, "name": name, "age": age] } catch { print("解析错误:\\(error)") return nil }}

// XML 示例let xmlData = """<root> <user id="42"> <name>伊万·彼得罗夫</name> <age>30</age> </user></root>"""if let result = parseWithAEXML(xmlString: xmlData) { print(result) // ["id": "42", "name": "伊万·彼得罗夫", "age": "30"]}


注意: AEXML 会将整个 XML 文档加载到内存中,因此不适合处理超大文件。



3. 创建 XML 文档



使用 AEXML 创建 XML 非常直观:



import AEXML

func createXML() -> String { let root = AEXMLElement(name: "catalog") root.addAttribute(name: "version", value: "1.0")

let book = AEXMLElement(name: "book") book.addAttribute(name: "id", value: "101") book.addChild(name: "title", value: "Swift 编程") book.addChild(name: "author", value: "苹果公司") book.addChild(name: "price", value: "29.99")

root.addChild(book)

let document = AEXMLDocument(root: root) return document.xml}

let xmlOutput = createXML()print(xmlOutput)/* 输出:<catalog version="1.0"> <book id="101"> <title>Swift 编程</title> <author>苹果公司</author> <price>29.99</price> </book></catalog>*/


4. 错误处理与最佳实践



  • 编码: 始终使用 .utf8 编码处理 XML 数据。
  • 大文件: 对于大文件,优先选择 XMLParser(SAX)而不是 AEXML(DOM)。
  • 命名空间: 处理 SOAP 等复杂 XML 时,注意命名空间处理。
  • 可选值: 始终对 .value 和 .attributes 进行可选解包。
  • 性能: 在 iOS/macOS 上,XMLParser 比 AEXML 更快,但编码更繁琐。


总结



在 Swift 中处理 XML 有两种主要方式:

  • XMLParser — 内置、高效、适合大文件,但需要手动管理状态。
  • AEXML — 第三方库、语法简洁、适合中小型文档,支持读写。

选择哪种方式取决于你的任务:对于简单的配置文件和 API 响应,AEXML 更方便;对于大型 RSS 订阅源或文档,XMLParser 更合适。

推荐