对PropertyList

时间:2018-05-20 16:16:34

标签: swift xml alamofire codable

我正在尝试使用样本https://www.w3schools.com/xml/note.xml中的Codable解析XML数据。

我的结构是

struct Note: Codable {
  var to: String?
  var from: String?
  var heading: String?
  var body: String?
}

但是,如果我发出以下请求,则会收到错误responseSerializationFailed : ResponseSerializationFailureReason "由于错误,无法将PropertyList序列化:\ n无法读取数据,因为它不在格式正确。"

let url = URL(string: "https://www.w3schools.com/xml/note.xml")
Alamofire.request(url!, method: .get, encoding: PropertyListEncoding.default).responsePropertyList { (response) in
  guard response.error == nil else {
    print(response.error!)
    exp.fulfill()
    return
  }

  print(response)

  if let data = response.data {
    print(data)
    let decoder = PropertyListDecoder()
    let note = try! decoder.decode(Note.self, from: data)
    print(note)
  }
}

你如何使用Alamofire中的responsePropertyList?

2 个答案:

答案 0 :(得分:0)

PropertyList文件虽然是XML格式,但它们需要遵循Apple的PropertyList DTD:http://www.apple.com/DTDs/PropertyList-1.0.dtd

如果要将常规XML文件(不遵循PropertyList DTD)映射到模型对象中,并且不介意使用外部库,可以尝试XMLMapper

此XML的模型应如下所示:

class Note: XMLMappable {
    var nodeName: String!

    var to: String?
    var from: String?
    var heading: String?
    var body: String?

    required init(map: XMLMap) { }

    func mapping(map: XMLMap) {
        to <- map["to"]
        from <- map["from"]
        heading <- map["heading"]
        body <- map["body"]
    }
}

您可以使用XMLMapper

从字符串映射它
let note = XMLMapper<Note>().map(XMLString: xmlString)

或者,如果您安装Requests subspec,则可以使用responseXMLObject(queue:keyPath:mapToObject:completionHandler:)功能,如:

let url = URL(string: "https://www.w3schools.com/xml/note.xml")
Alamofire.request(url!, method: .get, encoding: XMLEncoding.default).responseXMLObject { (response: DataResponse<Note>) in
    let note = response.result.value
    print(note?.from ?? "nil")
}

希望这有帮助。

答案 1 :(得分:0)

目前,Apple的 Codable 协议无法解码XML。虽然Plist是XML,但XML不一定是Plist,除非它遵循某种格式。

虽然有很多第三方库,但我建议你看一下XMLParsing library。该库包含 XMLDecoder XMLEncoder ,它使用Apple自己的 Codable 协议,并基于Apple的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>

符合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文件夹。

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不包含该属性,则可能意味着这些元素中没有任何元素。
  4. XMLEncoder和JSONEncoder之间的差异

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

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