Parse XML data in swift Parse XML data in swift xml xml

Parse XML data in swift


Because your XML contains all of the values with attributes of the element, you don't need to implement foundCharacters. Just didStartElement, e.g., your parser delegate might look as simple as:

var song: String?var artist: String?func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {    switch elementName {    case "Song":   song   = attributeDict["title"]    case "Artist": artist = attributeDict["name"]    default:       break    }}

Two observations:

  1. I'd be inclined to pull this parsing code out of the view controller, though, and put it in a dedicated object, to help prevent "view controller bloat".

  2. I'd also use URLSession in case the response to request happens to be a little slow. Generally, one should avoid using XMLParser(contentsOf:), because that performs the request synchronously.

    In your case, since you’re requesting the data from localhost, perhaps that’s less of a concern. But, still, it’s prudent to always perform HTTP requests asynchronously.

Anyway, that might yield something like:

class SongParser: NSObject {    var song: String?    var artist: String?        class func requestSong(completionHandler: @escaping (String?, String?, Error?) -> Void) {        let url = URL(string: "http://localhost/jazler/NowOnAir.xml")!        let task = URLSession.shared.dataTask(with: url) { data, _, error in            guard let data = data, error == nil else {                DispatchQueue.main.async {                    completionHandler(nil, nil, error)                }                return            }                        let delegate = SongParser()            let parser = XMLParser(data: data)            parser.delegate = delegate            parser.parse()            DispatchQueue.main.async {                completionHandler(delegate.song, delegate.artist, parser.parserError)            }        }        task.resume()    }}extension SongParser: XMLParserDelegate {    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {        switch elementName {        case "Song":   song   = attributeDict["title"]        case "Artist": artist = attributeDict["name"]        default:       break        }    }    }

And you'd use it like so:

SongParser.requestSong { song, artist, error in    guard let song = song, let artist = artist, error == nil else {        print(error ?? "Unknown error")        return    }        print("Song:", song)    print("Artist:", artist)}


First convert your xml into NSData and call the parser to parse it.

//converting into NSDatavar data: Data? = theXML.data(using: .utf8)//initiate  NSXMLParser with this datavar parser: XMLParser? = XMLParser(data: data ?? Data())//setting delegateparser?.delegate = self//call the method to parsevar result: Bool? = parser?.parse()parser?.shouldResolveExternalEntities = true

Now, you need to implement the NSXMLParser delegate into your class.

func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {currentElement = elementNameprint("CurrentElementl: [\(elementName)]")}func parser(_ parser: XMLParser, foundCharacters string: String) {print("foundCharacters: [\(string)]")}

You will find the value under key of your xml.