Parse an XML file in chunks without waiting for complete download in Swift
There are basically two type of parser: SAX and DOM. As per your requirement, where you are updating UITableView as soon as XML element received, It is perfectly clear that you will have to use SAX parser only. (DOM parser parsed the entire document and builds up an in-memory representation that you can query for different elements).
There are two popular SAX parser for iOS as listed below:
1)NSXMLParser (This has been renamed to XMLParser) - included by default with the iPhone SDK.
2)libxml2 - is an Open Source library that is included by default with the iPhone SDK
Apple has made an excellent code sample called XMLPerformance that allows you to compare the time it takes to parse a ~900KB XML document containing the top 300 iTunes songs with both the NSXML and libxml2 APIs.
Ok, here’s a graph that shows the peak memory usage by parser (this was obtained through running the various methods through the Object Allocations tool)
Data clearly shows that libxml2’s SAX method (Which you already tried) is the best option as far as peak memory usage is concerned.
On the other hand, implementing XMLParser is quite easy. Below is my example snippet which i tried using it.
In your class declaration, implement the XMLParserDelegate protocol
class ViewController: UIViewController,XMLParserDelegate {override func viewDidLoad() { super.viewDidLoad()
Use below method to initialize the parser:
func xmlParser(){ posts = [] parser = XMLParser(contentsOf:(NSURL(string:"http://images.apple.com/main/rss/hotnews/hotnews.rss"))! as URL)! parser.delegate = self parser.parse()}
Once you initialize the delegate, below delegate methods will get called as and when needed:
func parserDidStartDocument(_ parser: XMLParser) { print("started")}func parserDidEndDocument(_ parser: XMLParser) { print("ended")}func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { print("didEndElement")}func parser(_ parser: XMLParser, foundCharacters string: String) { print("foundCharacters")}
There are other delegate methods as well which you can call according to your requirements.
The below solution may help you out. I have explored about your question and succeed some what as a result below. But I can't able to test the below solution lack of API's. Try with your available Endpoints. Hope it will help you.
func xmlStream() { let task = URLSession.shared.streamTask(withHostName: "chat.example.com", port: 5555) task.readData(ofMinLength: 16384, maxLength: 65536, timeout: 30.0) { (data, eof, error) in let parser = XMLParser(data: data!) parser.delegate = self if parser.parse() { //print result } } task.resume() }//XML parser methods
Moreover this may guide you.