swift - Swift 中的 Codable 和 XMLParser

标签 swift xml-parsing codable

使用新的 Swift4 Codable协议(protocol)适用于 JSON 解码(如 herehere 或许多其他贡献中所述)。然而,当涉及到 XML 解析时,我找不到任何关于这是否 Codable 的信息。协议(protocol)也可用于 XML 解码。
我尝试使用 XMLParser(如下面的代码摘录所示)。但是我没有使用“Codable”协议(protocol)来简化 XML 解析过程。我将如何使用 Codable协议(protocol)正是为了简化 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 方法:
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解析协议(protocol)?

最佳答案

目前,Apple 的 Codable 协议(protocol)没有解码 XML 的方法。

虽然有很多第三方库可以解析 XML,但 XMLParsing library包含 XML解码器 XML编码器它使用 Apple 自己的 Codable 协议(protocol),并基于 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>

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)
}

与第三方协议(protocol)相比,使用 Apple 的 Codable 协议(protocol)有很多好处。例如,如果 Apple 决定开始支持 XML,您就不必重构。

有关此库示例的完整列表,请参阅存储库中的 Sample XML 文件夹。

为了符合 XML 标准,Apple 的解码器和编码器之间存在一些差异。这些如下:

XMLDecoder 和 JSONDecoder 的区别
  • XMLDecoder.DateDecodingStrategy有一个名为 keyFormatted 的额外案例.这种情况下需要一个为您提供 CodingKey 的闭包,您可以为所提供的 key 提供正确的 DateFormatter。这只是 JSONDecoder 的 DateDecodingStrategy 的一个便利案例。
  • XMLDecoder.DataDecodingStrategy有一个名为 keyFormatted 的额外案例.这种情况下需要一个为您提供 CodingKey 的闭包,您可以为所提供的 key 提供正确的数据或 nil。这只是 JSONDecoder 的 DataDecodingStrategy 的一个方便案例。
  • 如果符合 Codable 协议(protocol)的对象有一个数组,并且正在解析的 XML 中不包含该数组元素,则 XMLDecoder 会为该属性分配一个空数组。这是因为 XML 标准规定如果 XML 不包含该属性,则可能意味着这些元素中的零个。

  • XMLEncoder 和 JSONEncoder 的区别
  • 包含一个名为 StringEncodingStrategy 的选项,这个枚举有两个选项,deferredToStringcdata . deferredToString 选项是默认选项,会将字符串编码为简单字符串。如果选择了 cdata,所有字符串都将被编码为 CData。
  • encode函数比 JSONEncoder 接受两个额外的参数。该函数中的第一个附加参数是一个 RootKey 字符串,它将整个 XML 包装在一个名为该键的元素中。此参数是必需的。第二个参数是一个XMLHeader,它是一个可选参数,可以带版本、编码策略和独立状态,如果你想在编码的xml中包含这些信息。
  • 关于swift - Swift 中的 Codable 和 XMLParser,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47684714/

    相关文章:

    ios - 检索 Realm Swift 中存储的数据

    ios - 更新约束

    javascript - 获取子节点时 XML Null

    java - 如何处理 Org.Apache.Axiom.Om.OmException : Com. Ctc.Wstx.Exc.Wstxunexpectedcharexception : Illegal Character ((Ctrl-Char, 代码 25))

    ios - 将 Codable/Encodable 快速转换为 JSON 对象

    ios - snapchat 如何调整图像大小?

    ios - 自定义 Collection View 并在 Collection View 的单元格之间创建空间

    c# - 这在 python 中相当于什么

    json - 如何使用 swift Codable 协议(protocol)解码以 "["开头的 JSON

    swift - 使用 Decodable 进行 JSON 解析时,optional 和 decodeIfPresent 有什么区别?