Parsing XML Web Service in iOS With Swift

XML Parsing in iOS with Swift

The bullet answer is, you are here to learn XML Parsing in swift 3.0. Day by day the data is tremendously increasing and making it difficult to express in a simple format. There should be some standard formats of the data coming from the server in order to pick the right values from the huge amount of data. The most familiar way of expressing data, coming from server is either by JSON or XML. These two parsing methods, JSON parsing for JSON data and XML Parsing for XML data simplifies developer job to filter the values we needed. Many developers feel comfortable in working with JSON than XML. But it’s very important to know XML parsing also. As few API calls still provide in XML format. I think you already know enough about the importance of parsing(JSON or XML) in our development life. In this tutorial, we will see step-by-step process of XML Parsing. Will try to give a glimpse of knowledge on XML parsing by end of this tutorial.

This tutorial implemented using following elements:

1

XMLParser (part of iOS SDK)

2

Swift 3.0

3

XCode 8.3

#1

The XML format of the data looks like below.

<Response>
<IP>4.2.2.2</IP>
<CountryCode>US</CountryCode>
<CountryName>United States</CountryName>
<RegionCode/>
<RegionName/>
<City/>
<ZipCode/>
<TimeZone/>
<Latitude>37.751</Latitude>
<Longitude>-97.822</Longitude>
<MetroCode>0</MetroCode>
</Response>
XML Format Data

To explain in this tutorial, I’m getting XML Data from API which I got randomly from internet. You can search for free xml APIs on internet for making any sample apps. freegeoip.net provides a public HTTP API for software developers to search the geolocation of IP addresses. I’m using API provided by it.

#2

Initial Setup

Start creating a new application with Single-View-Application template in XCode.

Initial-Setup

After taking application template , our aim is to bring data from server using sample url. Write this data bringing functionality in one method and call from ViewDidLoad(life cycle method). For network call, I’m not using any third party library instead using the most powerful class provided by Apple i.e, URLSession. Write below method to bring data.

func getXMLDataFromServer(){  
    let url = NSURL(string: "https://freegeoip.net/xml/4.2.2.2")  
     
    //Creating data task  
    let task = URLSession.shared.dataTask(with: url! as URL) { (data, response, error) in  
         
        if data == nil {  
            print("dataTaskWithRequest error: \(String(describing: error?.localizedDescription))")  
            return  
        }  
         
        let parser = XMLParser(data: data!)  
        parser.delegate = self  
        parser.parse()  
         
    }  
     
    task.resume()  
  
}
XML Parsing in Swift

In the above method, dataTask(With:) method of URLSession will bring the data from server with URL. We are passing data came from server to XMLParser. We are assigning delegate to self to get callbacks for delegate methods in the same class. While parsing, XMLParserDelegate methods will be called in this class. And also Conform XMParserDelegate protocol, next to the ViewController name. Don’t forget!!!

class ViewController: UIViewController, XMLParserDelegate {  

There are five important delegate methods of XML parser which are called while parsing. Those five methods are,

  1. func parser(_ parser: XMLParser, didStartElement elementName: String, ….) – will be called when XMLParser see the starting of the tag. For an example, in <IP>4.2.2.2</IP> it reads starting tag i.,e ‘<IP>’ in this case.
  2. func parser(_ parser: XMLParser, didEndElement elementName: String, ….) – will be called when XML Parser see the ending of the tag. For an example, in <IP>4.2.2.2</IP> it reads ending tag i.,e ‘</IP>’ in this case.
  3. func parser(_ parser: XMLParser, foundCharacters string: String) – The most important method of parsing. The values we look for can be picked up from this method only. In our case <IP>4.2.2.2</IP>, the value 4.2.2.2 will be read.
  4. func parserDidEndDocument(_ parser: XMLParser) – This method will be called once total parsing is completed. UI updating method can be called from here to update the parsed data.
  5. func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) – If anything goes wrong, this method will be fired. If the structure of the format is not correct, the parsing likely to be fail.

Now we implement above delegate methods in our project. The code inside these methods will be like this.

//MARK:- XML Delegate methods  
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {  
    currentParsingElement = elementName  
    if elementName == "Response" {  
        print("Started parsing...")  
    }  
}  
  
func parser(_ parser: XMLParser, foundCharacters string: String) {  
    let foundedChar = string.trimmingCharacters(in:NSCharacterSet.whitespacesAndNewlines)  
      
    if (!foundedChar.isEmpty) {  
        if currentParsingElement == "IP" {  
            ipAddr += foundedChar  
        }  
        else if currentParsingElement == "CountryCode" {  
            countryCode += foundedChar  
        }  
        else if currentParsingElement == "CountryName" {  
            countryName += foundedChar  
        }  
        else if currentParsingElement == "Latitude" {  
            latitude += foundedChar  
        }  
        else if currentParsingElement == "Longitude" {  
            longitude += foundedChar  
        }  
    }  
      
}  
  
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {  
    if elementName == "Response" {  
        print("Ended parsing...")  
          
    }  
}  
  
func parserDidEndDocument(_ parser: XMLParser) {  
    DispatchQueue.main.async {  
        // Update UI  
        self.displayOnUI()  
    }  
}  
  
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {  
    print("parseErrorOccurred: \(parseError)")  
}
XML Parsing in Swift

The response from the server started with tag “Response”, that’ why I checked in didStartElement whether element is equal to “Response” or not. That means, it’s begining of the parsing. We can also know the beginning of the parsing using another method called parserDidStartDocument. Opposite to this, we can find out ending of the parsing in didEndElement method by checking whether element is equal to “Response” again. (As this is the first element of the parsing).

In foundCharacters method the main logic resides. It reads values of elements. IP, CountryCode, CountryName, et.c. Once the parsing over, we are calling custom method displayOnUI() to update the values we picked up. We are running this on DispatchQueue.main.async main thread as the whole process of fetching & parsing of data is going in background thread, we shouldn’t update UI from background thread. In case if we do that, it will give following error:

“This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes. This will cause an exception in a future release.”

So update UI only from main thread. To do that, we are using DispatchQueue.main.async. In displayOnUI() method, the data will be given to IBoutlets to show it on device. The final output looks like below.

How to Parse XML Web Service in iOS With Swift

The whole code for this tutorial:

#3

Wrap it up…

Looks very easy right? Yeah, it’s much easier than what developers afraid of. Thanks to XMLParser class from apple. It made our job easy by providing great delegate methods. As the data more, the complexity with XMLParser increases. In those cases even few developers go for third party frameworks. There are pretty good frameworks for this purpose. The data we are getting here from parsing, we are using directly to show in view. But when you are practicing it, it’s always recommend to use modal objects to feed the data and use.

Sivajee Battina
I'm an iOS developer with the capability of working on multiple projects at a time. Hunting for bugs and killing them with programming sword is my habit for the most of the time. Love to help, share and learn knowledge through leading platforms like StackOverflow. If 100% bug-free software is impossible, I love to dare that impossibility.