Swift 中的 Codable 和 XMLParser
Codable and XMLParser in Swift
使用新的 Swift4 Codable
协议非常适合 JSON 解码(如 here or here 或许多其他贡献中所述)。然而,当涉及到 XML 解析时,我找不到任何关于此 Codable
协议是否也可用于 XML 解码的信息。
我尝试使用 XML解析器(如下面的代码摘录所示)。但是我没有使用“Codable”协议来简化XML-解析过程。我将如何准确地使用 Codable
协议来简化 XML-解析 ??
// the Fetching of the XML-data (excerpt shown here with a simple dataTask) :
let myTask = session.dataTask(with: myRequest) { (data, response, error) in
// check for error
guard error == nil else {
completionHandler(nil, error!)
return
}
// make sure we got data in the response
guard let responseData = data else {
let error = XMLFetchError.objectSerialization(reason: "No data in response")
completionHandler(nil, error)
return
}
// the responseData is XML !!!!!!!!!!!!!!
let parser = XMLParser(data: responseData)
parser.delegate = self
parser.parse()
}
myTask.resume()
对应的XMLParserDelegate-methods:
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
self.resultTrip = elementName
// print(elementName)
if (self.resultTrip == "TripResult") {
self.resultTime = ""
}
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
let data = string.trimmingCharacters(in: .whitespacesAndNewlines)
if data.count != 0 {
switch self.resultTrip {
case "TimetabledTime": self.resultTime = data
default: break
}
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
if self.resultTrip == "TripResult" {
// HERE IS THE MISSING BIT: HOW DO YOU USE A CODABLE struct ???
var myTrip = TripResult(from: <#Decoder#>)
myTrip.resultID = self.resultTrip
}
print(resultTime)
}
结构:
struct TripResult : Codable {
let resultId : String?
let trip : Trip?
enum CodingKeys: String, CodingKey {
case resultId = "ResultId"
case trip
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
resultId = try values.decodeIfPresent(String.self, forKey: .resultId)
trip = try Trip(from: decoder)
}
}
我将如何使用 Codable
结构?有没有关于如何使用 Codable
协议进行 XML 解析的好例子?
目前,Apple 的 Codable 协议无法解码 XML.
虽然有很多第三方库可以解析 XML,但 XMLParsing library 包含一个 XML 解码器 和一个 XMLEncoder 使用 Apple 自己的 Codable 协议,并基于 Apple 的 JSONEncoder/JSONDecoder 进行更改以适应 XML标准。
Link: https://github.com/ShawnMoore/XMLParsing
W3School 的 XML 要解析:
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
Swift 符合 Codable 的结构:
struct Note: Codable {
var to: String
var from: String
var heading: String
var body: String
}
XML解码器:
let data = Data(forResource: "note", withExtension: "xml") else { return nil }
let decoder = XMLDecoder()
do {
let note = try decoder.decode(Note.self, from: data)
} catch {
print(error)
}
XML编码器:
let encoder = XMLEncoder()
do {
let data = try encoder.encode(self, withRootKey: "note")
print(String(data: data, encoding: .utf8))
} catch {
print(error)
}
与第三方协议相比,使用 Apple 的 Codable 协议有很多好处。举个例子,如果 Apple 决定开始支持 XML,你就不必重构。
有关此库示例的完整列表,请参阅存储库中的示例 XML 文件夹。
Apple 的解码器和编码器之间存在一些差异以符合 XML 标准。这些如下:
XML解码器和 JSONDecoder 的区别
XMLDecoder.DateDecodingStrategy
有一个名为 keyFormatted
的额外案例。这种情况采用闭包,为您提供 CodingKey,您需要为所提供的密钥提供正确的 DateFormatter。这只是 JSONDecoder 的 DateDecodingStrategy 的一个方便案例。
XMLDecoder.DataDecodingStrategy
有一个名为 keyFormatted
的额外案例。这种情况采用一个闭包,为您提供 CodingKey,您可以为提供的密钥提供正确的数据或 nil。这只是 JSONDecoder 的 DataDecodingStrategy 的一个方便案例。
- 如果符合Codable协议的对象有数组,而被解析的XML不包含数组元素,XMLDecoder会给该属性赋一个空数组。这是因为 XML 标准说如果 XML 不包含该属性,则可能意味着这些元素为零。
XMLEncoder 和 JSONEncoder 的区别
包含一个名为StringEncodingStrategy
的选项,这个枚举有两个选项,deferredToString
和cdata
。 deferredToString 选项是默认选项,会将字符串编码为简单字符串。如果选择cdata,则所有字符串都会编码为CData。
encode
函数比 JSONEncoder 多接收两个参数。该函数中的第一个附加参数是一个 RootKey 字符串,它将整个 XML 包裹在一个名为该键的元素中。此参数是必需的。第二个参数是一个XMLHeader,这是一个可选参数,可以带版本,编码策略和独立状态,如果你想在编码的xml.
中包含这些信息
使用新的 Swift4 Codable
协议非常适合 JSON 解码(如 here or here 或许多其他贡献中所述)。然而,当涉及到 XML 解析时,我找不到任何关于此 Codable
协议是否也可用于 XML 解码的信息。
我尝试使用 XML解析器(如下面的代码摘录所示)。但是我没有使用“Codable”协议来简化XML-解析过程。我将如何准确地使用 Codable
协议来简化 XML-解析 ??
// the Fetching of the XML-data (excerpt shown here with a simple dataTask) :
let myTask = session.dataTask(with: myRequest) { (data, response, error) in
// check for error
guard error == nil else {
completionHandler(nil, error!)
return
}
// make sure we got data in the response
guard let responseData = data else {
let error = XMLFetchError.objectSerialization(reason: "No data in response")
completionHandler(nil, error)
return
}
// the responseData is XML !!!!!!!!!!!!!!
let parser = XMLParser(data: responseData)
parser.delegate = self
parser.parse()
}
myTask.resume()
对应的XMLParserDelegate-methods:
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
self.resultTrip = elementName
// print(elementName)
if (self.resultTrip == "TripResult") {
self.resultTime = ""
}
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
let data = string.trimmingCharacters(in: .whitespacesAndNewlines)
if data.count != 0 {
switch self.resultTrip {
case "TimetabledTime": self.resultTime = data
default: break
}
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
if self.resultTrip == "TripResult" {
// HERE IS THE MISSING BIT: HOW DO YOU USE A CODABLE struct ???
var myTrip = TripResult(from: <#Decoder#>)
myTrip.resultID = self.resultTrip
}
print(resultTime)
}
结构:
struct TripResult : Codable {
let resultId : String?
let trip : Trip?
enum CodingKeys: String, CodingKey {
case resultId = "ResultId"
case trip
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
resultId = try values.decodeIfPresent(String.self, forKey: .resultId)
trip = try Trip(from: decoder)
}
}
我将如何使用 Codable
结构?有没有关于如何使用 Codable
协议进行 XML 解析的好例子?
目前,Apple 的 Codable 协议无法解码 XML.
虽然有很多第三方库可以解析 XML,但 XMLParsing library 包含一个 XML 解码器 和一个 XMLEncoder 使用 Apple 自己的 Codable 协议,并基于 Apple 的 JSONEncoder/JSONDecoder 进行更改以适应 XML标准。
Link: https://github.com/ShawnMoore/XMLParsing
W3School 的 XML 要解析:
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
Swift 符合 Codable 的结构:
struct Note: Codable {
var to: String
var from: String
var heading: String
var body: String
}
XML解码器:
let data = Data(forResource: "note", withExtension: "xml") else { return nil }
let decoder = XMLDecoder()
do {
let note = try decoder.decode(Note.self, from: data)
} catch {
print(error)
}
XML编码器:
let encoder = XMLEncoder()
do {
let data = try encoder.encode(self, withRootKey: "note")
print(String(data: data, encoding: .utf8))
} catch {
print(error)
}
与第三方协议相比,使用 Apple 的 Codable 协议有很多好处。举个例子,如果 Apple 决定开始支持 XML,你就不必重构。
有关此库示例的完整列表,请参阅存储库中的示例 XML 文件夹。
Apple 的解码器和编码器之间存在一些差异以符合 XML 标准。这些如下:
XML解码器和 JSONDecoder 的区别
XMLDecoder.DateDecodingStrategy
有一个名为keyFormatted
的额外案例。这种情况采用闭包,为您提供 CodingKey,您需要为所提供的密钥提供正确的 DateFormatter。这只是 JSONDecoder 的 DateDecodingStrategy 的一个方便案例。XMLDecoder.DataDecodingStrategy
有一个名为keyFormatted
的额外案例。这种情况采用一个闭包,为您提供 CodingKey,您可以为提供的密钥提供正确的数据或 nil。这只是 JSONDecoder 的 DataDecodingStrategy 的一个方便案例。- 如果符合Codable协议的对象有数组,而被解析的XML不包含数组元素,XMLDecoder会给该属性赋一个空数组。这是因为 XML 标准说如果 XML 不包含该属性,则可能意味着这些元素为零。
XMLEncoder 和 JSONEncoder 的区别
包含一个名为
StringEncodingStrategy
的选项,这个枚举有两个选项,deferredToString
和cdata
。 deferredToString 选项是默认选项,会将字符串编码为简单字符串。如果选择cdata,则所有字符串都会编码为CData。
中包含这些信息encode
函数比 JSONEncoder 多接收两个参数。该函数中的第一个附加参数是一个 RootKey 字符串,它将整个 XML 包裹在一个名为该键的元素中。此参数是必需的。第二个参数是一个XMLHeader,这是一个可选参数,可以带版本,编码策略和独立状态,如果你想在编码的xml.