代码之家  ›  专栏  ›  技术社区  ›  SleepNot

Alamoire XML请求到属性列表

  •  1
  • SleepNot  · 技术社区  · 7 年前

    我正在尝试使用示例中的可编码项来分析XML数据 https://www.w3schools.com/xml/note.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)
      }
    }
    

    你到底是如何处理Alamoire中的ResponsePropertyList的?

    2 回复  |  直到 7 年前
        1
  •  0
  •   S.Moore    7 年前

    目前,苹果的 可编码的 协议没有解码XML的方法。虽然plist是XML,但是XML不一定是plist,除非它遵循某种格式。

    虽然有很多第三方图书馆,我建议你看看 XMLParsing library . 此库包含 XML解码器 和A XML编码器 使用苹果自己的 可编码的 协议,并基于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 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)
    }
    

    使用苹果有很多好处 可编码的 协议优于第三方协议。例如,如果Apple决定开始支持XML,就不必重构。

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


    为了适应XML标准,苹果的解码器和编码器之间存在一些差异。如下:

    xmlcoder和jsondecoder的区别

    1. XMLDecoder.DateDecodingStrategy 有一个题为 keyFormatted . 本例采用一个闭包,该闭包为您提供了一个编码密钥,并且由您为所提供的密钥提供正确的日期格式化程序。这只是一个方便的案例 日期编码策略 JSondecoder的。
    2. XMLDecoder.DataDecodingStrategy 有一个题为 关键格式 . 本例采用一个闭包,为您提供一个编码密钥,您可以为所提供的密钥提供正确的数据或零。这只是一个方便的案例 数据编码策略 JSondecoder的。
    3. 如果符合可编码协议的对象有一个数组,并且正在解析的XML不包含数组元素,则xmlcoder将为该属性分配一个空数组。这是因为XML标准规定,如果XML不包含属性,这可能意味着这些元素中没有任何元素。

    xmlEncoder和jsonEncoder之间的区别

    1. 包含一个名为 StringEncodingStrategy ,此枚举有两个选项, deferredToString cdata . 这个 延迟字符串 选项是默认值,将字符串编码为简单字符串。如果 计算机数据处理系统 如果选中,则所有字符串都将编码为CDATA。

    2. 这个 encode 函数接受了两个比jsonEncoder多的参数。函数中的第一个附加参数是 指定根键 将整个XML包装在名为该键的元素中的字符串。此参数是必需的。第二个参数是一个xmlHeader,它是一个可选参数,如果您希望将此信息包含在编码的xml中,它可以采用版本、编码策略和独立状态。

        2
  •  0
  •   gcharita    7 年前

    属性列表文件虽然是XML格式,但它们需要遵循Apple的属性列表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 可以使用的子规范 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")
    }
    

    希望这有帮助。