Parsing XML Using Swift
A complete tutorial to guide you through parsing XML in your iOS app using SWXMLHash, including a remote XML demo project
XML is a great way to store data in a standardized format. It can be used for a variety of different purposes, such as RSS feeds or storing information online that you want to be easily searchable. However, even though XML is typically user-friendly, the process of parsing it can sometimes be tedious and confusing. In this tutorial, I’ll show you how to parse XML files with Swift from start to finish. We’re going to cover everything from setting up your project and importing the necessary libraries, to iterating through each node. There’s no need to sweat! By the end of this tutorial, you’ll have an app that parses XML files with ease!
Getting Started
If you already have CocoaPods installed, skip step 1.
- You will need CocoaPods on your Mac for this to work, if you don’t already, type the following command to install it from your Mac terminal with Xcode installed:
sudo gem install cocoapods
. - Initiate your project by navigating to its root directory in terminal and running the “pod init” command as shown in this video.
- The library we will be using today, SWXMLHash, provides us with a translation from XML to a hash (dictionary of arrays) and makes them easy to extract into our code or objects. Modify your newly created “Podfile,” in your project’s root directory to add this library—
pod 'SWXMLHash', '~> 5.0.0'
as shown here:
4. Save the file and run the command pod install
on the same directory.
5. Use the new .xcworkspace file in the project’s root folder to launch it.
Creating the Data Model
For our XML data, we will be using a live public RSS feed from the New York Times World News. This data model consists of an enclosing <rss>
tag, followed by a <channel>
tag that contains RSS feed general information and a list of news <item>
tags.
For a simple demonstration, we’ll create an object with a title, url, and a pubDate (publication date).
In the ContentView’s struct, we can create an array to store the news items and some other variables to store general information about the RSS feed channel.
Retrieving and Parsing the XML Data
To retrieve and parse the XML data we will be using URLSession in combination with SWXMLHash as demonstrated below.
We initialize SWXMLHash with the following code: let xml = SWXMLHash.parse(feed)
and then use the xml
variable in combination with the tag names, that we know exist in the XML file, to obtain our data.
Since our RSS feed channel’s general information is structured starting with the <rss>
tag then the<channel>
tag, we can reach the data under it by using xml["rss"]["channel"]
.
For example, if we wanted the channel title, which is directly branched under the <channel>
tag, it would be xml["rss"]["channel"]["title"]
and so on for the rest of the elements. By adding .element!.text
at the end, we tell Swift that this value definitely exists and to read it as a string type.
Since there are multiple news <item>
tags, we need to iterate through them like an array, and we can do this using a for loop with the .all
extension. We can then parse the data for each item similar to the method we used in parsing our channel information.
I strongly recommend you reference this repository for more complicated parsing situations you may come across. There are some great complex examples provided.
Below is a simplified structure of the XML data provided by the URL, containing only the data we used in today’s example, for reference.
Reading the Publication Date
Making the date readable might seem like a tedious task, especially when the date looks something like this: Sat, 07 Aug 2021 06:00:08 +0000
, but it’s actually very easy! Referencing the website NSDateFormatter makes this task a lot easier. Under their examples section on the homepage you can see the format we need is: E, d MMM yyyy HH:mm:ss Z
. You can also click on the Reference tab to see what each one of these letters means.
Using DateFormatter in the code below we can create a reusable function to read our date as a string and return a Date type format to store in our data model.
We can then create another function that makes this date more user-friendly. In this case, I will use the DateFormatter format of: EEEE, MMM d, yyyy HH:mm
to provide us with a date with a military time that looks like this: Saturday, Aug 7, 2021 13:19
.
Displaying the Data
Now that we have everything stored, we can start building our user interface. For a simple user interface that demonstrates this example, we can create a VStack containing the channel name, URL, and image, along with a list containing another VStack of all the news items’ titles and publication date.
We also want to make each news item tappable and have it activate Safari, given the proper URL. We can do this using .onTapGesture
on the stack in our List and then call UIApplication.shared.open(URL(string: imageURL))
, with item.url being the URL we are passing in.
Note: AsyncImage is only available for iOS 15; This is used for image display. Comment lines 9 & 10 to run with no errors on iOS 14, without the image.
Wrapping Up
Your final result will look like this:
But if it doesn’t, don’t worry! The source code for the app pictured above is hosted here on GitHub.
Note: The Xcode project above has been compiled using XCode v13.0 Beta, if you need a working version for iOS14.0 and XCode v12.x, use this repository.
Remember to install the SWXMLHash dependency after downloading these repositories to avoid error messages trying to compile the project.
That’s It!
Get to parsing that XML and building more cool apps! If you have any questions, please reach out to me in the comments.