Swift4中的Codable和XMLParser

iKK*_*iKK 10 decode xml-parsing swift4 codable

使用Swift4,iOS11.1,Xcode9.1,

使用新的Swift4 typealiase"Codable"适用于JSON解码(如此此处或许多其他贡献中所述).但是,在XML解析方面,我找不到任何有关此"Codable"协议是否也可用于XML解码的信息.

我尝试使用XMLParser(可以在下面的代码中看到).但我没有使用"Codable"协议来简化XML解析过程.我怎么必须完全使用Codable协议来简化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()
Run Code Online (Sandbox Code Playgroud)

相应的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)
}
Run Code Online (Sandbox Code Playgroud)

结构:

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

我怎么必须使用'codable'结构?有没有关于如何使用Codable协议进行XML分析的好例子?任何帮助赞赏!

S.M*_*ore 16

目前,Apple的Codable协议没有办法解码XML.

虽然有大量的第三方库来解析XML,在XMLParsing库包含的XMLDecoderXMLEncoder使用苹果自己可编码协议,是基于苹果的JSONEncoder/JSONDecoder与变化,以适应XML的标准.

链接:https://github.com/ShawnMoore/XMLParsing


W3School的XML To Parse:

<note>
    <to>Tove</to>
    <from>Jani</from>
    <heading>Reminder</heading>
    <body>Don't forget me this weekend!</body>
</note>
Run Code Online (Sandbox Code Playgroud)

符合Codable的Swift Struct:

struct Note: Codable {
    var to: String
    var from: String
    var heading: String
    var body: String
}
Run Code Online (Sandbox Code Playgroud)

的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)
}
Run Code Online (Sandbox Code Playgroud)

XMLEncoder:

let encoder = XMLEncoder()

do {
   let data = try encoder.encode(self, withRootKey: "note")

   print(String(data: data, encoding: .utf8))
} catch {
   print(error)
}
Run Code Online (Sandbox Code Playgroud)

使用Apple的Codable协议比使用第三方协议有许多好处.例如,如果Apple决定开始支持XML,则不必重构.

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


Apple的解码器和编码器之间存在一些差异,以适应XML标准.这些如下:

XMLDecoder和JSONDecoder之间的差异

  1. XMLDecoder.DateDecodingStrategy有一个额外的案例标题keyFormatted.这种情况采用一个闭包,为您提供CodingKey,由您提供所提供密钥的正确DateFormatter.这只是JSONDecoder的DateDecodingStrategy 上的一个简便案例.
  2. XMLDecoder.DataDecodingStrategy有一个额外的案例标题keyFormatted.这种情况采用一个闭包,为您提供CodingKey,由您提供正确的数据或nil为提供的密钥.这只是JSONDecoder的DataDecodingStrategy 上的一个简便案例.
  3. 如果符合Codable协议的对象具有数组,并且正在解析的XML不包含数组元素,则XMLDecoder将为该属性分配一个空数组.这是因为XML标准表示如果XML不包含该属性,则可能意味着这些元素中没有任何元素.

XMLEncoder和JSONEncoder之间的差异

  1. 包含一个名为的选项StringEncodingStrategy,这个枚举有两个选项,deferredToStringcdata.该deferredToString选项是默认的,将编码字符串作为简单的字符串.如果选择了cdata,则所有字符串都将编码为CData.

  2. encode函数接受了比JSONEncoder更多的两个参数.函数中的第一个附加参数是RootKey字符串,它将整个XML包装在名为该键的元素中.此参数是必需的.第二个参数是XMLHeader,它是一个可选参数,如果要在编码的xml中包含此信息,则可以采用版本,编码策略和独立状态.

  • 非常感谢 S.Moore 的超级详细解释! (2认同)