Alamofire XML запрос к PropertyList - PullRequest
0 голосов
/ 20 мая 2018

Я пытаюсь проанализировать XML-данные, используя Codable из примера 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)
  }
}

Как именно вы работаетес ответомPropertyList в Alamofire?

Ответы [ 2 ]

0 голосов
/ 22 мая 2018

В настоящее время протокол Apple Codable не позволяет декодировать XML.Хотя Plist - это XML, XML не обязательно является Plist, если он не соответствует определенному формату.

Хотя существует множество сторонних библиотек, я бы посоветовал вам взглянуть на XMLParsing library .Эта библиотека содержит XMLDecoder и XMLEncoder , который использует собственный протокол Apple Codable , и основан на Apple JSONEncoder / JSONDecoder с изменениями, соответствующими стандарту XML.

Ссылка: https://github.com/ShawnMoore/XMLParsing


XML W3School для анализа:

<note>
    <to>Tove</to>
    <from>Jani</from>
    <heading>Reminder</heading>
    <body>Don't forget me this weekend!</body>
</note>

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, вам не придется проводить рефакторинг.

Полный список примеров этой библиотеки см. В папке «Образец XML» в хранилище.


Существует несколько различий между декодерами и кодировщиками Apple, соответствующими стандарту XML.Они следующие:

Различия между XMLDecoder и JSONDecoder

  1. XMLDecoder.DateDecodingStrategy имеют дополнительный регистр под названием keyFormatted.В этом случае происходит закрытие, которое дает вам CodingKey, и вы должны предоставить правильный DateFormatter для предоставленного ключа.Это просто вспомогательный случай для DateDecodingStrategy JSONDecoder.
  2. XMLDecoder.DataDecodingStrategy имеет дополнительный случай, озаглавленный keyFormatted.В этом случае происходит закрытие, которое дает вам CodingKey, и вы должны предоставить правильные данные или ноль для предоставленного ключа.Это просто удобный случай для DataDecodingStrategy JSONDecoder.
  3. Если объект, соответствующий протоколу Codable, имеет массив, а анализируемый XML не содержит элемент массива, XMLDecoder будетприсвоить атрибуту пустой массив.Это связано с тем, что в стандарте XML говорится, что если XML не содержит атрибута, это может означать, что таких элементов нет.

Различия между XMLEncoder и JSONEncoder

  1. Содержит параметр с именем StringEncodingStrategy, у этого перечисления есть два параметра, deferredToString и cdata.Параметр deferredToString является значением по умолчанию и будет кодировать строки как простые строки.Если выбран cdata , все строки будут закодированы как CData.

  2. Функция encode принимает два дополнительных параметра, чем JSONEncoder.Первый дополнительный параметр в функции - это строка RootKey , в которой весь XML-код будет заключен в элемент с именем этого ключа.Этот параметр является обязательным.Второй параметр - это XMLHeader, который является необязательным параметром, который может принимать версию, стратегию кодирования и автономный статус, если вы хотите включить эту информацию в кодированный xml.

0 голосов
/ 21 мая 2018

Файлы PropertyList, хотя и в формате XML, должны соответствовать DTL AppleListList: http://www.apple.com/DTDs/PropertyList-1.0.dtd

Если вы хотите отобразить обычный XML-файл (не соответствующий DTD PropertyList) в объект модели ивы не против использовать внешнюю библиотеку, вы можете попробовать 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")
}

Надеюсь, это поможет.

...