XMLWrangler

GitHub release Tests Codacy Badge codecov Docs

在 Swift 中轻松处理 XML。

安装

将以下依赖项添加到您的 Package.swift 文件中

.package(url: "https://github.com/sersoft-gmbh/xmlwrangler", from: "6.0.0"),

兼容性

Swift XMLWrangler 包
< 5.2.0 1.x.y - 3.x.y
>= 5.3.0, < 5.9.0 5.x.y
>= 5.9.0 6.x.y

用法

XMLElement

XML 中的每个元素都由 XMLElement 结构体表示。它具有三个属性,name 反映元素的标签名称,attributes 包含元素的所有属性,以及 content 描述元素的内容。内容是一个集合,其 Element 是一个枚举。该枚举有两种情况:.string.element。集合中的顺序是内容被找到的顺序。因此,如果一个元素首先包含一些文本,然后包含一个子元素,最后又包含一些文本,则 content 将包含一个 .string,其关联的 StringPart 是第一个文本。接下来将是一个 .element,其关联的 XMLElement 将是子元素。最后,将是另一个 .string,其中包含最后一个文本。

虽然您可以创建一个 XMLElement,其内容为 [.string("abc"), .string("def"), .element(XMLElement(name: "test"))],并且它也会生成有效的 XML,但可以将其清理为 [.string("abcdef"), .element(XMLElement(name: "test"))]。为了实现这一点,建议使用 XMLElement.content 上的各种 append 函数,或者甚至直接在 XMLElement 上使用,当您不能保证内容在创建时被清理的情况下。如果您的元素是使用空内容 ([]) 创建的,并且您追加上面的每个内容元素,append 函数会确保它们将 “def” 字符串追加到第一个 “abc” 字符串,而不是向内容添加另一个 .string。如果由于某种原因,您仍然遇到内容具有连续 .string 元素的情况,则有一个方便的函数 compress()(或其非变异兄弟函数 compressed()),它将这些 .string 元素合并为一个。

一个 XMLElement 可以与另一个元素进行比较,并且如果所有三个属性(nameattributescontent)都相等,则被认为是相等的。这意味着对于一个大型树,根元素的所有子元素都将被比较。因此,在比较大型树时要小心,并在必要时回退到手动比较 name 和/或 attributesXMLElement 也符合 Identifiable 协议,并使用 name 作为 id

使用 XMLWrangler 序列化和解析 XML 都依赖于 XMLElement

解析 XML

可以使用 XMLElement 上的静态函数来解析现有的 XML。您可以解析给定的 Data 对象或包含 XML 的 String。如果解析成功,则返回解析后的根对象。否则,沿途发生的任何错误都会被抛出。抛出的错误是由 Foundation.XMLParser 创建的错误。

do {
    let xml = """
              <?xml version='1.0' encoding='UTF-8'?>
              <root myattr='myvalue'>
                  <child1/>
                  <child2>some text</child2>
              </root>
              """
    let root = try XMLElement.parse(xml)
} catch {
    print("Something went wrong while parsing: \(error)")
}

在此示例中,root.name.rawValue 当然将是 "root"root.content 将包含两个 .element。第一个将具有关联的 XMLElement,其 name"child1",内容为空 content。第二个 .elementXMLElementname 将是 "child2",其内容将包含一个 .string,其中关联了 "some text"root.attributes 将包含键 "myattr" 的值 "myvalue"

序列化 XMLElement

由于您可以解析 XML,因此您也可以将 XMLElement 转换为 String。为此,XMLElement 上有两个函数。第一个函数只是将 XMLElement 转换为 String。这通过创建开始和结束标签(其中开始标签包含 attributes,如果可用)并将元素的 content 放在两者之间来实现。此外,content 在序列化之前会被压缩(使用前面提到的 compress 函数)。

var root = XMLElement(name: "root", attributes: ["myattr": "myvalue"])
root.content.append(element: "child1")
root.content.append(element: XMLElement(name: "child2", content: "some text"))

let xmlString = xml.serialize() // -> "<root myattr=\"myvalue\"><child1/><child2>some text</child2></root>"

如果还应添加传统的 XML 标头,则还有第二个函数,它接受版本和文档编码作为附加参数,但在其他方面遵循相同的规则

var root = XMLElement(name: "root", attributes: ["myattr": "myvalue"])
root.content.append(element: "child1")
root.content.append(element: XMLElement(name: "child2", content: "some text"))

let xmlDocumentString = root.serializeAsDocument(at: DocumentVersion(major: 1), using: .utf8)
// -> "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root myattr=\"myvalue\"><child1/><child2>some text</child2></root>"

请注意,XMLWrangler 不会根据给定的编码转义字符串。它只是使用它来生成文档标头。

这两个函数都可以接受一个附加参数 options,其中包含一组控制序列化行为的选项。目前,以下选项是可能的

类型安全

XMLWrangler 将始终在内部将所有内容和属性提取为 String。这是因为 XML 本身不区分类型,例如 JSON 那样。但是,有许多辅助函数可以安全地查找和转换 XMLElement 的内容和属性

当出现问题时,所有这些方法都会抛出一个错误 (XMLElement.LookupError),而不是返回可选值。如果您更喜欢可选值,您可以始终使用 try?。有关更多信息,请查看标题文档,其中更详细地描述了这些方法。

可能的功能

虽然尚未集成,但以下功能可能会提供附加值,并可能在未来加入 XMLWrangler

文档

API 使用标题文档进行文档化。如果您更喜欢将文档作为网页查看,则有一个 在线版本 可供您使用。

贡献

如果您发现 XMLWrangler 中存在错误/希望看到新功能,可以通过以下几种方式提供帮助

许可证 & 版权

请参阅 LICENSE 文件。

版权所有 © 2016-2023 ser.soft GmbH。