使用Swift4,iOS11.1,Xcode9.1,
使用新的Swift4类型别名“ Codable”可很好地用于JSON解码(如here或here或许多其他贡献所述)。但是,就XML解析而言,我找不到有关此“ Codable”协议是否也可以用于XML解码的任何信息。
我尝试使用XMLParser(可以在下面的代码验证中看到)。但是我没有使用“ Codable”协议来简化XML解析过程。我将如何确切地使用Codable-protocol来简化XML解析?
// 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方法:
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-protocol用于XMLparsing,有没有很好的示例?
任何帮助表示赞赏!
最佳答案
当前,Apple的Codable协议没有解码XML的方法。
尽管有很多第三方库可以解析XML,但XMLParsing library包含XMLDecoder和XMLEncoder,它们使用Apple自己的Codable协议,并且基于Apple的JSONEncoder / JSONDecoder,并进行了更改以适合XML标准。
链接: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>
符合Codable的Swift Struct:
struct Note: Codable {
var to: String
var from: String
var heading: String
var body: String
}
XMLDecoder:
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)
}
XMLEncoder:
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,则无需进行重构。
有关此库示例的完整列表,请参见存储库中的Sample XML文件夹。
苹果公司的解码器和编码器在符合XML标准方面有一些区别。这些如下:
XMLDecoder和JSONDecoder之间的区别
XMLDecoder.DateDecodingStrategy
有一个额外的案例,标题为keyFormatted
。这种情况下需要给您一个CodingKey一个闭包,由您来为所提供的密钥提供正确的DateFormatter。这只是JSONDecoder的DateDecodingStrategy上的一种方便情况。XMLDecoder.DataDecodingStrategy
有一个额外的案例,标题为keyFormatted
。这种情况下需要给您一个CodingKey一个闭包,然后由您来为所提供的密钥提供正确的数据或nil。这只是JSONDecoder的DataDecodingStrategy上的一种方便情况。如果符合Codable协议的对象具有数组,并且要解析的XML不包含array元素,则XMLDecoder将为该属性分配一个空数组。这是因为XML标准指出如果XML不包含该属性,则可能意味着这些元素为零。
XMLEncoder和JSONEncoder之间的区别
包含一个名为
StringEncodingStrategy
的选项,此枚举有两个选项,deferredToString
和cdata
。默认值为deferredToString选项,它将字符串编码为简单字符串。如果选择了cdata,则所有字符串都将被编码为CData。encode
函数比JSONEncoder接受两个附加参数。函数中的第一个附加参数是RootKey字符串,该字符串会将整个XML包装在名为该键的元素中。此参数是必需的。第二个参数是XMLHeader,如果要在编码的xml中包含此信息,则它是一个可选参数,可以采用版本,编码策略和独立状态。关于xml-parsing - Swift4中的Codable和XMLParser,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47684714/