You can use NSXMLParser (or XMLParser, as of now, in Swift 3). NSXMLDocument is also a feature, but not available for iOS, while XMLParser is available for all OSs. Here's a simple implementation of your case ...
struct Person {
var name = " "
var sex = " "
var age = " "
}
let inputString = "<a><name> abc </name><sex> male </sex><age> 13 </age></a><a><name> bcd </name><sex> male </sex><age> 14 </age></a>"
let document = "<doc>" + inputString + "</doc>"
if let data = document.data(using: .utf16) {
let xmlParser = XMLParser(data: data)
let delegate = MyDelegate()
xmlParser.delegate = delegate
if xmlParser.parse() {
print("Result \(delegate.personArray)")
}
}
class MyDelegate: NSObject, XMLParserDelegate {
var personArray: [Person] = []
enum State { case none, name, sex, age }
var state: State = .none
var newPerson: Person? = nil
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
switch elementName {
case "a" :
self.newPerson = Person()
self.state = .none
case "sex":
self.state = .sex
case "name":
self.state = .name
case "age":
self.state = .age
default:
self.state = .none
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
if let newPerson = self.newPerson, elementName == "a" {
self.personArray.append(newPerson)
self.newPerson = nil
}
self.state = .none
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
guard let _ = self.newPerson else { return }
switch self.state {
case .name:
self.newPerson!.name = string
case .age:
self.newPerson!.age = string
case .sex:
self.newPerson!.sex = string
default:
break
}
}
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
}
}
To make it work on playgrounds, you need to first declare a delegate (on the call), but he reads this way better ...
source
share