I wrote a pod for mapping XML to objects, called XMLMapper. (uses the same technique as the ObjectMapper)
For what you want to achieve you can simply use XMLSerialization
class like:
let url = URL(string: "http://www.urlexample.com/file.xml")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
do{
let xmlDictionary = try XMLSerialization.xmlObject(with: data!) as? [String: Any]
} catch {
print("Serialization error occurred: \(error.localizedDescription)")
}
}
task.resume()
You can also implement the XMLMappable
protocol like:
class XMLResponse: XMLMappable {
var nodeName: String!
var record: Record?
required init(map: XMLMap) {
}
func mapping(map: XMLMap) {
record <- map["record"]
}
}
class Record: XMLMappable {
var nodeName: String!
var empName: String!
var empPhone: String!
var empEmail: String?
var empAddress: String?
var empAddress1: String?
required init(map: XMLMap) {
}
func mapping(map: XMLMap) {
empName <- map["EmpName"]
empPhone <- map["EmpPhone"]
empEmail <- map["EmpEmail"]
empAddress <- map["EmpAddress"]
empAddress1 <- map["EmpAddress1"]
}
}
And map the response XML into that objects by using XMLMapper
class:
let xmlResponse = XMLMapper<XMLResponse>().map(XMLObject: xmlDictionary)
UPDATE: Cover @fahim-parkar's comment.
To map an object (or many objects in an array) you use the same technique.
For example to map the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>Apple Hot News</title>
<link>http://www.apple.com/hotnews/</link>
<description>Hot News provided by Apple.</description>
<language>en-us</language>
<copyright>Copyright 2016, Apple Inc.</copyright>
<pubDate>Tue, 26 Apr 2016 15:53:26 PDT</pubDate>
<lastBuildDate>Tue, 26 Apr 2016 15:53:26 PDT</lastBuildDate>
<category>Apple</category>
<generator>In house</generator>
<docs>http://blogs.law.harvard.edu/tech/rss/</docs>
<item>
<title>Apple Reports Second Quarter Results</title>
<link>http://www.apple.com/pr/library/2016/04/26Apple-Reports-Second-Quarter-Results.html?sr=hotnews.rss</link>
<description>Apple today announced financial results for its fiscal 2016 second quarter ended March 26. The company posted quarterly revenue of $50.6 billion and quarterly net income of $10.5 billion, or $1.90 per diluted share. These results compare to revenue of $58 billion and net income of $13.6 billion, or $2.33 per diluted share, in the year-ago quarter. Gross margin was 39.4 percent compared to 40.8 percent in the year-ago quarter. International sales accounted for 67 percent of the quarter’s revenue. “Our team executed extremely well in the face of strong macroeconomic headwinds,” said Tim Cook, Apple’s CEO. “We are very happy with the continued strong growth in revenue from Services, thanks to the incredible strength of the Apple ecosystem and our growing base of over 1 billion active devices.”</description>
<pubDate>Tue, 26 Apr 2016 14:44:21 PDT</pubDate>
</item>
<item>
<title>Final Cut Pro X helps small company delight world’s biggest clients</title>
<link>http://www.apple.com/final-cut-pro/in-action/trim-editing/?sr=hotnews.rss</link>
<description>When Trim Editing started creating music videos over a decade ago, just paying the rent was a huge accomplishment. Now, the small East London company is crafting award-winning visuals for big brands — like Audi, Nike, Adidas, and Guinness — propelled by the power of Final Cut Pro X. The video editing software’s comprehensive features allow Trim Editing to organize film and audio clips, pull together compelling projects, and make changes on the fly. “When I’m playing back an edit for a director, they’ll say, ‘Okay, let’s go and make those changes I talked about.’ I’ll say, ‘Oh, no, they’re already done,’ and we’ll jump back and watch it again. People can’t believe that I’ve magically done the change before we even finish playback,” says editor Thomas Grove Carter. </description>
<pubDate>Wed, 20 Apr 2016 10:05:59 PDT</pubDate>
</item>
<item>
<title>Apple Introduces 9.7-inch iPad Pro</title>
<link>http://www.apple.com/ipad-pro/?sr=hotnews.rss</link>
<description>Apple today introduced the 9.7-inch iPad Pro, which at just under one pound features a new pro Retina display with greater brightness, wider color gamut, lower reflectivity, Night Shift mode, and new True Tone display technology. The new iPad Pro also has a 64-bit A9X chip that rivals most portable PCs. “iPad Pro is a new generation of iPad that is indispensable and immersive, enabling people to be more productive and more creative. It’s incredibly fast, extremely portable, and completely natural to use with your fingers, Apple Pencil, and Smart Keyboard. And now it comes in two sizes,” said Philip Schiller, Apple’s senior vice president of Worldwide Marketing.</description>
<pubDate>Mon, 21 Mar 2016 12:00:03 PDT</pubDate>
</item>
</channel>
</rss>
You need to create the model classes like:
class RSSFeed: XMLMappable {
var nodeName: String!
var channel: Channel?
required init?(map: XMLMap) {}
func mapping(map: XMLMap) {
channel <- map["channel"]
}
}
class Channel: XMLMappable {
var nodeName: String!
var title: String?
var link: URL?
var description: String?
var language: String?
var copyright: String?
var pubDate: Date?
var lastBuildDate: Date?
var category: String?
var generator: String?
var docs: URL?
var items: [Item]?
private static var dateFormatter: DateFormatter = {
var dateFormatter = DateFormatter()
dateFormatter,dateFormat = "E, d MMM yyyy HH:mm:ss zzz"
return dateFormatter
}()
required init?(map: XMLMap) {}
func mapping(map: XMLMap) {
title <- map["title"]
link <- (map["link"], XMLURLTransform())
description <- map["description"]
language <- map["language"]
copyright <- map["copyright"]
pubDate <- (map["pubDate"], XMLDateFormatterTransform(dateFormatter: Channel.dateFormatter))
lastBuildDate <- (map["lastBuildDate"], XMLDateFormatterTransform(dateFormatter: Channel.dateFormatter))
category <- map["category"]
generator <- map["generator"]
docs <- (map["docs"], XMLURLTransform())
items <- map["item"]
}
}
class Item: XMLMappable {
var nodeName: String!
var title: String?
var link: URL?
var description: String?
var pubDate: Date?
private static var dateFormatter: DateFormatter = {
var dateFormatter = DateFormatter()
dateFormatter,dateFormat = "E, d MMM yyyy HH:mm:ss zzz"
return dateFormatter
}()
required init?(map: XMLMap) {}
func mapping(map: XMLMap) {
title <- map["title"]
link <- (map["link"], XMLURLTransform())
description <- map["description"]
pubDate <- (map["pubDate"], XMLDateFormatterTransform(dateFormatter: Item.dateFormatter))
}
}
Using the native URLSession
you can map the RSS XML response using XMLSerialization
and XMLMapper
:
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
do {
let xmlDictionary = try XMLSerialization.xmlObject(with: data!) as? [String: Any]
let rssFeed = XMLMapper<RSSFeed>().map(XMLObject: xmlDictionary)
print(rssFeed?.items?.first?.title ?? "nil")
} catch {
print("Serialization error occurred: \(error.localizedDescription)")
}
}
task.resume()
If you don't mind using Alamofire for the request, you will find XMLMapper/Requests subspec a lot easier using this code to map:
Alamofire.request(url).responseXMLObject { (response: DataResponse<RSSFeed>) in
let rssFeed = response.result.value
print(rssFeed?.items?.first?.title ?? "nil")
}
I hope this is helpful.