Swift - 生成XML格式数据1(使用XMLParsing库)
作者:hangge | 2018-10-12 08:10
我之前写过两篇文章介绍如何解析 XML 格式的数据,有使用第三方库的、也有使用原生代码的:

(2)运行结果如下:
(2)运行结果如下:
(2)解析前我们先创建对应的数据模型(model):
(3)接下来读取文件并进行解析,XMLParsing 会自动将其映射成对应的模型。
(4)运行结果如下:

(2)如果模型属性名与其不一致的话,使用 CodingKeys 指定每个属性对应的标签名。
(2)如果我们想要将其转换成日期属性(Date),则需设置好相关的日期格式化器即可。
下面我接着演示如何生成 XML 数据,这个同样需要借助第三方库来实现。本文先介绍 XMLParsing 这个第三方 XML 库。
一、XMLParsing 库的安装与介绍
1,基本介绍
(1)我们知道 Swift4 中引入了 Codable 协议,可以用来实现 JSON 数据的 Encode 和 Decode。但它并没有办法解析 XML。
(2)而 XMLParsing 库同样使用了 Swift4 的 Codable 协议,不过它在苹果的 JSONEncoder/JSONDecoder 基础上增加了 XMLEncoder 和 XMLDecoder,从而适应 XML 标准。
2,安装配置
(1)首先到它的 GitHub 主页上将库下载到本地:
(2)解压后将 Sources 文件夹下的整个 XMLParsing 拖到我们项目中来即可。

二、基本用法
1,模型创建
首先我们创建好图书以及书籍类别的数据模型(model),注意它们要遵循 Codable 协议。
import Foundation
//包含所有的图书分类
struct Catalogs: Codable {
var catalogs: [Catalog]
}
//具体的图书分类
struct Catalog: Codable {
//所属类型
var genre: Genre
//该分类下的图书
var books: [Book]
}
//具体图书
struct Book: Codable {
var id: String
var title: String
var price: Double
var publishDate: Date
}
//图书类书
enum Genre: String, Codable {
case computer = "计算机"
case horror = "恐怖故事"
case sciFi = "科幻小说"
}
2,使用样例
(1)下面代码我们创建一系列的书籍数据,并使用 XMLParsing 将其转换为相应 XML 字符串。
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//创建第一个图书分类数据
let book1 = Book(id: "101", title: "神经网络设计", price: 99,
publishDate: string2Date(string: "2018-09-11"))
let book2 = Book(id: "102", title: "代码大全", price: 108,
publishDate: string2Date(string: "2006-06-20"))
let book3 = Book(id: "103", title: "算法导论", price: 85,
publishDate: string2Date(string: "2006-05-04"))
let catalog1 = Catalog(genre: .computer, books: [book1, book2, book3])
//创建第二个图书分类数据
let book4 = Book(id: "201", title: "三体", price: 70,
publishDate: string2Date(string: "2017-08-10"))
let book5 = Book(id: "202", title: "海底两万里", price: 90,
publishDate: string2Date(string: "2002-02-20"))
let catalog2 = Catalog(genre: .sciFi, books: [book4, book5])
//所有分类数据集合
let catalogs = Catalogs(catalogs: [catalog1, catalog2])
//将数据转为对应的XML字符串
let encoder = XMLEncoder()
do {
let data = try encoder.encode(catalogs, withRootKey: "data") //根节点标签为data
let xml = String(data: data, encoding: .utf8)
print(xml!)
} catch {
print(error)
}
}
//将字符串转成日期
func string2Date(string:String) -> Date {
let dateFormatter = DateFormatter.init()
dateFormatter.dateFormat = "yyyy-MM-dd"
let date = dateFormatter.date(from: string)
return date!
}
}
(2)运行结果如下:

三、进阶用法
1,修改标签名
(1)默认情况下生成 XML 数据时,使用属性名作为对应的标签名。我们可以在模型中使用 CodingKeys 指定每个属性转换后使用的标签名。
import Foundation
//包含所有的图书分类
struct Catalogs: Codable {
var catalogs: [Catalog]
//指定属性对应的标签文字(不改变的话则使用属性名)
enum CodingKeys: String, CodingKey {
case catalogs = "catalog"
}
}
//具体的图书分类
struct Catalog: Codable {
//所属类型
var genre: Genre
//该分类下的图书
var books: [Book]
//指定属性对应的标签文字(不改变的话则使用属性名)
enum CodingKeys: String, CodingKey {
case genre
case books = "book"
}
}
//具体图书
struct Book: Codable {
var id: String
var title: String
var price: Double
var publishDate: Date
//指定属性对应的标签文字(不改变的话则使用属性名)
enum CodingKeys: String, CodingKey {
case id, title, price
case publishDate = "publish_date"
}
}
//图书类书
enum Genre: String, Codable {
case computer = "计算机"
case horror = "恐怖故事"
case sciFi = "科幻小说"
}
(2)运行结果如下:

2,日期格式化
默认情况下日期类型(Date)的属性值输出的是数字形式,我们可以使用日期格式化器将其格式化成指定日期格式。
//创建第一个图书分类数据
let book1 = Book(id: "101", title: "神经网络设计", price: 99,
publishDate: string2Date(string: "2018-09-11"))
let book2 = Book(id: "102", title: "代码大全", price: 108,
publishDate: string2Date(string: "2006-06-20"))
let book3 = Book(id: "103", title: "算法导论", price: 85,
publishDate: string2Date(string: "2006-05-04"))
let catalog1 = Catalog(genre: .computer, books: [book1, book2, book3])
//创建第二个图书分类数据
let book4 = Book(id: "201", title: "三体", price: 70,
publishDate: string2Date(string: "2017-08-10"))
let book5 = Book(id: "202", title: "海底两万里", price: 90,
publishDate: string2Date(string: "2002-02-20"))
let catalog2 = Catalog(genre: .sciFi, books: [book4, book5])
//所有分类数据集合
let catalogs = Catalogs(catalogs: [catalog1, catalog2])
//将数据转为对应的XML字符串
let encoder = XMLEncoder()
//设置日期格式化器
let formatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}()
encoder.dateEncodingStrategy = .formatted(formatter)
do {
let data = try encoder.encode(catalogs, withRootKey: "data")
let xml = String(data: data, encoding: .utf8)
print(xml!)
} catch {
print(error)
}
3,设置 XML 头声明信息(XML Header)
//将数据转为对应的XML字符串
let encoder = XMLEncoder()
do {
let data = try encoder.encode(catalogs, withRootKey: "data",
header: XMLHeader(version: 1.0, encoding: "utf-8", standalone: "no"))
let xml = String(data: data, encoding: .utf8)
print(xml!)
} catch {
print(error)
}
附:使用 XMLParsing 库解析 XML 数据
XMLParsing 除了可以将模型转成 XML 数据外,同样可以将 XML 数据解析成对应的模型。下面通过样例进行演示。
1,基本用法
(1)假设我们有个 xml 数据文件(books.xml),内容如下:
<data>
<catalogs>
<genre>计算机</genre>
<books>
<publishDate>558288000</publishDate>
<title>神经网络设计</title>
<id>101</id>
<price>99</price>
</books>
<books>
<publishDate>172425600</publishDate>
<title>代码大全</title>
<id>102</id>
<price>108</price>
</books>
</catalogs>
<catalogs>
<genre>科幻小说</genre>
<books>
<publishDate>523987200</publishDate>
<title>三体</title>
<id>201</id>
<price>70</price>
</books>
</catalogs>
</data>
(2)解析前我们先创建对应的数据模型(model):
import Foundation
//包含所有的图书分类
struct Catalogs: Codable {
var catalogs: [Catalog]
}
//具体的图书分类
struct Catalog: Codable {
//所属类型
var genre: Genre
//该分类下的图书
var books: [Book]
}
//具体图书
struct Book: Codable {
var id: String
var title: String
var price: Double
var publishDate: Date
}
//图书类书
enum Genre: String, Codable {
case computer = "计算机"
case horror = "恐怖故事"
case sciFi = "科幻小说"
}
(3)接下来读取文件并进行解析,XMLParsing 会自动将其映射成对应的模型。
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//获取xml数据
let file = Bundle.main.path(forResource: "books", ofType: "xml")
let url = URL(fileURLWithPath: file!)
let xmlData = try! Data(contentsOf: url)
//解析数据
let decoder = XMLDecoder()
let catalogs: Catalogs?
do {
//将数据解析成对应的模型
catalogs = try decoder.decode(Catalogs.self, from: xmlData)
//遍历输出
for catalog in catalogs!.catalogs {
print("--- \(catalog.genre.rawValue) ---")
for book in catalog.books {
print(book.title, book.price, book.publishDate)
}
}
} catch {
print(error)
}
}
}
(4)运行结果如下:

2,设置映射的标签名
(1)上面的样例中我们模型里的属性是和 XML 数据中标签名一一对应的。假设 xml 数据中的标签名如下:

(2)如果模型属性名与其不一致的话,使用 CodingKeys 指定每个属性对应的标签名。
import Foundation
//包含所有的图书分类
struct Catalogs: Codable {
var catalogs: [Catalog]
//指定属性对应的标签文字(不改变的话则使用属性名)
enum CodingKeys: String, CodingKey {
case catalogs = "catalog"
}
}
//具体的图书分类
struct Catalog: Codable {
//所属类型
var genre: Genre
//该分类下的图书
var books: [Book]
//指定属性对应的标签文字(不改变的话则使用属性名)
enum CodingKeys: String, CodingKey {
case genre
case books = "book"
}
}
//具体图书
struct Book: Codable {
var id: String
var title: String
var price: Double
var publishDate: Date
//指定属性对应的标签文字(不改变的话则使用属性名)
enum CodingKeys: String, CodingKey {
case id, title, price
case publishDate = "publish_date"
}
}
//图书类书
enum Genre: String, Codable {
case computer = "计算机"
case horror = "恐怖故事"
case sciFi = "科幻小说"
}
3,日期格式化
(1)XML 文件中的日期可能会是各种各样的形式,比如下面这种常见的“年-月-日”形式:
(2)如果我们想要将其转换成日期属性(Date),则需设置好相关的日期格式化器即可。
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//获取xml数据
let file = Bundle.main.path(forResource: "books", ofType: "xml")
let url = URL(fileURLWithPath: file!)
let xmlData = try! Data(contentsOf: url)
//解析数据
let decoder = XMLDecoder()
let catalogs: Catalogs?
//设置日期格式化器
let formatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}()
decoder.dateDecodingStrategy = .formatted(formatter)
do {
//将数据解析成对应的模型
catalogs = try decoder.decode(Catalogs.self, from: xmlData)
//遍历输出
for catalog in catalogs!.catalogs {
print("--- \(catalog.genre.rawValue) ---")
for book in catalog.books {
print(book.title, book.price, book.publishDate)
}
}
} catch {
print(error)
}
}
}
全部评论(0)