import Foundation class PropfindParser: NSObject, XMLParserDelegate { private let data: Data private var result: [DenoteNote] = [] private var currentHref = "" private var currentModifiedDate: Date? private var isCollection = false private var currentText = "" private let dateFormatter: DateFormatter = { let f = DateFormatter() f.locale = Locale(identifier: "en_US_POSIX") f.dateFormat = "EEE, dd MMM yyyy HH:mm:ss zzz" return f }() init(data: Data) { self.data = data } func parse() -> [DenoteNote] { let parser = XMLParser(data: data) parser.delegate = self parser.shouldProcessNamespaces = true parser.parse() return result } func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName: String?, attributes: [String: String] = [:]) { currentText = "" switch elementName { case "response": currentHref = "" currentModifiedDate = nil isCollection = false case "collection": isCollection = true default: break } } func parser(_ parser: XMLParser, foundCharacters string: String) { currentText += string } func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName: String?) { let text = currentText.trimmingCharacters(in: .whitespacesAndNewlines) switch elementName { case "href": currentHref = text case "getlastmodified": currentModifiedDate = dateFormatter.date(from: text) case "response": guard !isCollection else { return } if let note = DenoteNote.parse(href: currentHref, modifiedDate: currentModifiedDate) { result.append(note) } default: break } } }