问题描述
使用 Swift4、iOS11.1、Xcode9.1,
Using Swift4, iOS11.1, Xcode9.1,
使用新的 Swift4 类型别名Codable"非常适合 JSON 解码(如此处 或 这里 或许多其他贡献).然而,在 XML 解析方面,我找不到任何关于这种可编码"协议是否也可以用于 XML 解码的信息.
Using the new Swift4 typealiase "Codable" works well for JSON-decoding (as explained here or here or in many other contributions). However, as it comes to XML-parsing, I couldn't find any information on whether this "Codable" protocol could also be used for XML-decoding.
我尝试使用 XMLParser(可以在下面的 code-excerts 中看到).但是我没有使用可编码"协议来简化 XML 解析过程.我该如何使用 Codable-protocol 来简化 XML 解析??
I tried to use the XMLParser (as can be seen in code-excerts below). But I failed to used the "Codable" protocol as to simplify the XML-parsing process. How would I have to use the Codable-protocol exactly to simplify XML-parsing ??
// the Fetching of the XML-data (excert 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:
The corresponding 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 协议进行 XML 解析的好例子?任何帮助表示赞赏!
How would I have to use the 'codable' struct ?? Is there any nice example on how to use the Codable-protocol for XMLparsing ??Any help appreciated !
推荐答案
目前,Apple 的 Codable 协议没有办法解码 XML.
Currently, Apple's Codable protocol does not have a way to decode XML.
虽然有很多第三方库可以解析 XML,但 XMLParsing 库 包含一个 XMLDecoder 和一个 XMLEncoder,它使用 Apple 自己的 Codable 协议,并且基于 Apple 的 JSONEncoder/JSONDecoder 并进行了更改以适应 XML 标准.
While there are plenty of third party libraries to parse XML, the XMLParsing library contains a XMLDecoder and a XMLEncoder that uses Apple's own Codable protocol, and is based on Apple's JSONEncoder/JSONDecoder with changes to fit the XML standard.
链接: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 Struct 符合 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,你就不必重构了.
There are a number of benefits for using Apple's Codable protocol over that of a third-party's protocol. Take for example if Apple decides to begin supporting XML, you would not have to refactor.
有关此库示例的完整列表,请参阅存储库中的 Sample XML 文件夹.
For a full list of examples of this library, see the Sample XML folder in the repository.
Apple 的解码器和编码器之间存在一些差异以符合 XML 标准.它们如下:
There are a few differences between Apple's Decoders and Encoders to fit the XML standard. These are as follows:
XMLDecoder 和 JSONDecoder 的区别
XMLDecoder.DateDecodingStrategy
有一个名为keyFormatted
的额外案例.这种情况下需要一个为您提供 CodingKey 的闭包,您可以为所提供的密钥提供正确的 DateFormatter.这只是 JSONDecoder 的 DateDecodingStrategy 上的一个便利案例.XMLDecoder.DataDecodingStrategy
有一个名为keyFormatted
的额外案例.这种情况下需要一个为您提供 CodingKey 的闭包,您可以为所提供的密钥提供正确的数据或 nil.这只是 JSONDecoder 的 DataDecodingStrategy 上的一个便利案例.- 如果符合 Codable 协议的对象有一个数组,并且被解析的 XML 不包含该数组元素,XMLDecoder 会为该属性分配一个空数组.这是因为 XML 标准规定,如果 XML 不包含该属性,则可能意味着这些元素为零.
XMLDecoder.DateDecodingStrategy
has an extra case titledkeyFormatted
. This case takes a closure that gives you a CodingKey, and it is up to you to provide the correct DateFormatter for the provided key. This is simply a convenience case on the DateDecodingStrategy of JSONDecoder.XMLDecoder.DataDecodingStrategy
has an extra case titledkeyFormatted
. This case takes a closure that gives you a CodingKey, and it is up to you to provide the correct data or nil for the provided key. This is simply a convenience case on the DataDecodingStrategy of JSONDecoder.- If the object conforming to the Codable protocol has an array, and the XML being parsed does not contain the array element, XMLDecoder will assign an empty array to the attribute. This is because the XML standard says if the XML does not contain the attribute, that could mean that there are zero of those elements.
XMLEncoder 和 JSONEncoder 的区别
包含一个名为
StringEncodingStrategy
的选项,这个枚举有两个选项,deferredToString
和cdata
.deferredToString 选项是默认选项,会将字符串编码为简单字符串.如果选择cdata,所有的字符串都会被编码为CData.
Contains an option called
StringEncodingStrategy
, this enum has two options,deferredToString
andcdata
. The deferredToString option is default and will encode strings as simple strings. If cdata is selected, all strings will be encoded as CData.
encode
函数比 JSONEncoder 接收两个额外的参数.该函数中的第一个附加参数是一个 RootKey 字符串,它将整个 XML 包装在一个名为该键的元素中.此参数是必需的.第二个参数是一个XMLHeader,它是一个可选参数,可以带版本、编码策略和独立状态,如果你想在编码的xml中包含这些信息.
The encode
function takes in two additional parameters than JSONEncoder does. The first additional parameter in the function is a RootKey string that will have the entire XML wrapped in an element named that key. This parameter is required. The second parameter is an XMLHeader, which is an optional parameter that can take the version, encoding strategy and standalone status, if you want to include this information in the encoded xml.
这篇关于Swift4 中的 Codable 和 XMLParser的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!