Swift4中的Codable和XMLParser [英] Codable and XMLParser in Swift4

查看:46
本文介绍了Swift4中的Codable和XMLParser的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Using Swift4, iOS11.1, Xcode9.1,

使用新的Swift4类型别名 Codable可很好地用于JSON解码(如这里此处或其他其他内容)。但是,在XML解析方面,我找不到有关此 Codable协议是否也可以用于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(如下面的代码验证所示)。但是我没有使用 Codable协议来简化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方法:

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-protocol进行XMLparsing有没有很好的例子?
任何帮助表示赞赏!

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 协议没有办法

Currently, Apple's Codable protocol does not have a way to decode XML.

尽管有很多第三方库可以解析XML,但 XMLParsing库包含一个 XMLDecoder 和一个使用Apple自己的 Codable 协议并基于Apple的 XMLEncoder 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>

符合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,则不必进行重构。

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.

有关该库示例的完整列表,请参见

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之间的差异


  1. XMLDecoder.DateDecodingStrategy 有一个额外的案例,标题为 keyFormatted 。这种情况下需要给您一个CodingKey一个闭包,由您来为所提供的密钥提供正确的DateFormatter。这只是JSONDecoder的 DateDecodingStrategy 上的一种方便情况。

  2. XMLDecoder.DataDecodingStrategy 有一个额外的情况。标题为 keyFormatted 。这种情况下需要给您提供CodingKey的闭包,由您决定是否为提供的密钥提供正确的数据或nil。这只是JSONDecoder的 DataDecodingStrategy 上的一种方便情况。

  3. 如果符合Codable协议的对象具有数组,并且所解析的XML不包含数组元素,XMLDecoder将为属性分配一个空数组。这是因为XML标准规定如果XML不包含该属性,则可能意味着这些元素为零。

  1. XMLDecoder.DateDecodingStrategy has an extra case titled keyFormatted. 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.
  2. XMLDecoder.DataDecodingStrategy has an extra case titled keyFormatted. 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.
  3. 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之间的差异


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

  1. Contains an option called StringEncodingStrategy, this enum has two options, deferredToString and cdata. The deferredToString option is default and will encode strings as simple strings. If cdata is selected, all strings will be encoded as CData.

编码函数比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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆