It's my first iOS application, and I kinda have some trouble with getting data from a XML. I need to get the song name and the artist from a XML file that looks like this:
<?xml version="1.0" encoding="utf-8"?>
<Schedule System="Jazler">
<Event status="happening" startTime="19:14:30" eventType="song">
<Announcement Display="Now On Air:"/>
<Song title="E timpul">
<Artist name="Revers">
</Artist>
<Jazler ID="16490"/>
<PlayLister ID=""/>
<Media runTime="03:03"/>
<Expire Time="19:17:33"/>
</Song>
</Event>
</Schedule>
Until now I think I created the parser, but I have no idea how to get the data from it, and the online tutorials are confusing me a bit...
self.parser = XMLParser(contentsOf: URL(string:"http://localhost/jazler/NowOnAir.xml")!)!
self.parser.delegate = self as? XMLParserDelegate
let success:Bool = self.parser.parse()
if success {
print("success")
} else {
print("parse failure!")
}
Your help is much appreciated & thanks in advance.
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:
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".
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 NSData
var data: Data? = theXML.data(using: .utf8)
//initiate NSXMLParser with this data
var parser: XMLParser? = XMLParser(data: data ?? Data())
//setting delegate
parser?.delegate = self
//call the method to parse
var 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 = elementName
print("CurrentElementl: [\(elementName)]")
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
print("foundCharacters: [\(string)]")
}
You will find the value under key of your xml.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With