[Xcode 实际操作]七、文件与数据-(16)解析XML文档
本文将演示如何解析XML文档。
项目中已添加一份XML文档:worker.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <workers> 3 <worker id='1'> 4 <name>Jerry</name> 5 <age>35</age> 6 <salary>25600</salary> 7 </worker> 8 <worker id='2'> 9 <name>Stone</name> 10 <age>33</age> 11 <salary>27800</salary> 12 </worker> 13 </workers>
此外还添加了一个实体类,实体类的字段,对应于XML中的元素。
1 import Foundation 2 3 class Worker: NSObject 4 { 5 var id : String = "" 6 var name : String = "" 7 var age : String = "" 8 var salary : String = "" 9 }
在项目导航区,打开视图控制器的代码文件【ViewController.swift】
1 import UIKit 2 3 //首先引入文档的解析代理协议XMLParserDelegate, 4 //主要的解析工作,都是靠代理来实现的。 5 class ViewController: UIViewController, XMLParserDelegate { 6 7 //为当前的视图控制器类,添加三个属性。 8 //第一个属性:解析后的对象数组 9 fileprivate var workers : NSMutableArray! = NSMutableArray() 10 //第二个属性:当前遍历到的标签名称 11 fileprivate var currentTag : String! 12 //第三个属性:正在生成的实体对象 13 fileprivate var currentWork : Worker! 14 15 override func viewDidLoad() { 16 super.viewDidLoad() 17 // Do any additional setup after loading the view, typically from a nib. 18 19 //从项目的目录结构中,读取等待解析的文档 20 var xmlPath : String = Bundle.main.path(forResource: "worker", ofType: "xml")! 21 22 //添加一条异常捕捉语句,用于读取指定位置上的文件 23 do 24 { 25 //读取指定位置上的文件, 26 //将读取后的内容,转换为字符串常量, 27 let xmlContent : NSString! = try NSString(contentsOfFile: xmlPath as String, encoding: 1) 28 //在控制台打印输出读取的内容 29 print("\(String(describing: xmlContent))") 30 31 //创建一个解析对象,并设置字符的编码模式 32 let myParse = XMLParser(data: xmlContent.data(using: String.Encoding.utf8.rawValue)!) 33 //设置解析对象的代理,为当前视图控制器对象 34 myParse.delegate = self 35 36 //开始解析文档 37 if(!myParse.parse()) 38 { 39 //当解析错误时 40 //在控制台输出错误日志 41 print("\(String(describing: myParse.parserError))") 42 } 43 } 44 catch 45 { 46 print("Error.") 47 } 48 } 49 50 //添加一个代理方法,用来标识解析动作的开始 51 func parserDidStartDocument(_ parser: XMLParser) { 52 print("------------ Begin") 53 } 54 55 //添加一个代理方法,用来标识解析动作的结束 56 //当完成解析任务后,在控制台打印输出最终结果 57 func parserDidEndDocument(_ parser: XMLParser) { 58 print("------------ End") 59 //添加一个循环语句 60 for i in 0 ..< workers.count 61 { 62 //获得数组中的指定索引的对象 63 let work = workers[i] as! Worker 64 //在控制台依次打印输出,解析后的各项内容。 65 print(work.id) 66 print(work.name) 67 print(work.age) 68 print(work.salary) 69 } 70 } 71 72 //添加一个代理方法,当解析到一个开始标签时,调用此方法 73 func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) { 74 //获得当前标签的名称 75 currentTag = elementName 76 //判断当前的标签,是否对应于指定的实体类。 77 if currentTag == "worker" 78 { 79 //如果当前标签对应于实体类, 80 //则初始化一个实体类对象。 81 currentWork = Worker() 82 //并设置实体类对象唯一标识符的值,为当前标签的属性值。 83 currentWork.id = attributeDict["id"]! 84 } 85 } 86 87 //添加一个代理方法,当解析到一个标签的全部或部分时,调用此方法 88 func parser(_ parser: XMLParser, foundCharacters string: String) { 89 //获得检索到的字符串,并去除字符串中的空格和换行符 90 let str:String! = string.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) 91 //根据当前标签的名称,设置实体类名称属性的值 92 if currentTag == "name" && str != "" 93 { 94 currentWork.name = string 95 } 96 //设置实体类年龄属性的值 97 else if currentTag == "age" && str != "" 98 { 99 currentWork.age = string 100 } 101 //设置实体类薪水属性的值 102 else if currentTag == "salary" && str != "" 103 { 104 currentWork.salary = string 105 } 106 } 107 108 //添加一个代理方法,当解析到一个结束标签时,调用此方法 109 func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { 110 //根据XML文档的结构,如果结束标签的名称时Salary, 111 //表示对一个实体类的标签检索即将结束, 112 //则将实体对象添加到数组中 113 if elementName == "salary" 114 { 115 workers.add(currentWork) 116 } 117 } 118 119 override func didReceiveMemoryWarning() { 120 super.didReceiveMemoryWarning() 121 // Dispose of any resources that can be recreated. 122 } 123 }