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)