Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Parse XML in iOS with Swift 4.0 with A SOAP Web Service Apple RSS News

A Simple XML Parsing Example in ios with Swift 4.0. 


ASMX - SOAP-XML(Simple Object Access Protocol - Extensible Markup Language)
SOAP - Simple Object Access Protocol itis a xml-based messaging protocol for exchanging information among computer
"ASMX provide the ability to build service that send message using the SOAP"

  • SOAP is communication via internet
  • SOAP can extend HTTP for XML messaging
  • Data transfer for web service

"XML stands for Extensible Markup Language. XML is a markup language much like HTML. XML was designed to store and transport data. XML was designed to be self-descriptive."
its defines a set of rules for encoding documents in a format human-readable and machine-readable.

In this tutorial parse xml web service(apple rss news - https://developer.apple.com/news/rss/news.rss) using a XMLParser object. The results of the parse the data in a tableView in UITableViewController. This tutorial is made with Xcode 10 and built for iOS 12.

Create New Project Xcode a new Single View App


Enter Project Name, Team name, Organization name, or identifier and select language swift.


Now design TableView, Cell in UITableViewController


1. First Create a XMLParser Class - //  XMLParser.swift
in struct declare properties of object


import Foundation
import UIKit

struct RSSItem {
    var title: String
    var description: String
    var pubDate: String
}

// download xml from a server
// parse xml to Foundation object
// call back


class FeedParser: NSObject, XMLParserDelegate {
    private var rssItem: [RSSItem] = []
    private var currentElement = ""
    
    private var currentTitle = ""
    {
        didSet{
            currentTitle = currentTitle.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        }
    }
    private var currentDescription = "" {
        didSet{
            currentDescription = currentDescription.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        }
    }
    
    private var currentPubDate = "" {
        didSet{
            currentPubDate = currentPubDate.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        }
    }
    private var parserCompletionHandeler: (([RSSItem])-> Void)?

// Download XML
    
   func parseFeed(url: String, completionHandler: (([RSSItem])-> Void)?){
        self.parserCompletionHandeler = completionHandler
        let request = URLRequest(url: URL(string: url)!)
        let urlSession = URLSession.shared
        let task = urlSession.dataTask(with: request) { (data, response, error) in
            guard let data = data else{
                if let error = error {
                    print(error.localizedDescription)
                }
                return
            }
            // parse our xml data
            
            let parser = XMLParser(data: data)
            parser.delegate = self
            parser.parse()
        }
        task.resume()
    }

    // XML Parser Delegate

    
    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
        currentElement = elementName
        
        if currentElement == "item"{
            currentTitle = ""
            currentDescription = ""
            currentPubDate = ""
        }
        
        
    }
    func parser(_ parser: XMLParser, foundCharacters string: String) {
        switch currentElement {
        case "title": currentTitle += string
            case "description": currentDescription += string
            case "pubDate": currentPubDate += string
        default: break
        }
    }
    func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        if elementName == "item" {
            let rssItem = RSSItem(title: currentTitle, description: currentDescription, pubDate: currentPubDate)
            self.rssItem.append(rssItem)
        }
    }
    func parserDidEndDocument(_ parser: XMLParser) {
        parserCompletionHandeler?(rssItem)
    }
    func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
        print(parseError.localizedDescription )
    }
}


2. Then Create TableView Cell Properties where are to display data. - NewsTableCell.swift

import Foundation
import UIKit

enum CellState {
    case expanded
    case collapsed
}

class NewsTableCell: UITableViewCell {
    
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var descriptionLabel: UILabel!{
        didSet{
            descriptionLabel.numberOfLines = 3
        }
    }
    
    @IBOutlet weak var dateLabel: UILabel!
    
    var item: RSSItem! {
        didSet {
            titleLabel.text = item.title
            descriptionLabel.text = item.description
            dateLabel.text = item.pubDate
            
            
        }
    }
}

3. Fatch Data UITableViewController TableView. // NewsTableViewController.swift

import Foundation
import UIKit

class NewsTableViewController: UITableViewController {
    private var rssItems: [RSSItem]?
    private var cellState: [CellState]?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.estimatedRowHeight = 155.0
        tableView.rowHeight = UITableView.automaticDimension
        fetchData()
    }
    private func fetchData(){
    let feedparser = FeedParser()
        feedparser.parseFeed(url: "https://developer.apple.com/news/rss/news.rss") { (rssItems) in
            self.rssItems = rssItems
            self.cellState = Array(repeating: .collapsed, count: rssItems.count)
            OperationQueue.main.addOperation {
                self.tableView.reloadSections(IndexSet(integer: 0), with: .left)
            }
            
        }
        
    }
    
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        guard let rssItems = rssItems else {
            return 0
        }
        return rssItems.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! NewsTableCell
        if let item = rssItems?[indexPath.row]{
            cell.item = item
            cell.selectionStyle = .none
            if let cellState = cellState{
                cell.descriptionLabel.numberOfLines = (cellState[indexPath.row] == .expanded) ? 0 : 4
            }
        }
        return cell
        
    }
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        let cell = tableView.cellForRow(at: indexPath) as! NewsTableCell
        tableView.beginUpdates()
        cell.descriptionLabel.numberOfLines = (cell.descriptionLabel.numberOfLines == 0) ? 3 : 0
        cellState?[indexPath.row] = (cell.descriptionLabel.numberOfLines == 0) ? .expanded: .collapsed
        tableView.endUpdates() 
    }
}

Finally Output - here parse data with XMLParser






This post first appeared on IOS Developer Live, please read the originial post: here

Share the post

Parse XML in iOS with Swift 4.0 with A SOAP Web Service Apple RSS News

×

Subscribe to Ios Developer Live

Get updates delivered right to your inbox!

Thank you for your subscription

×