解析XML文件的两种方式 SAX和DOM

1、数据解析

  1. 解析的基本概念
  • 所谓“解析”:从事先规定好的格式中提取数据
  • 解析的前提:提前约定好格式,数据提供方按照格式提供数据、数据获取方则按照格式获取数据
  • iOS开发常见的解析:XML解析、JSON解析

2、XML数据结构

  • XML:Extensible Markup language(可扩展标记语言),主流数据格式之一,可以用来存储和传输数据。
  • XML数据格式的功能
    • 数据交换
    • 内容管理
    • 用作配置文件
  • XML数据结构的语法
    • 声明
    • 节点使用一对标签表示:起始和结束标签。
    • 根节点是起始节点,只有一个,节点可以嵌套。
    • 节点可以有值,存储在一对儿标签中。
  • XML示例

 

3、JSON数据结构

  • JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。JSON采用完全独立于语言的文本格式,易于阅读和编写,同时也易于机器解析和生成。这些特性使JSON成为理想的数据交换语言。
  • JSON数据结构的语法
    • JSON文件有两种结构:
    • 对象:“名称/值”对的集合。不同的语言中,它被理解为对象,记录,结构,字典,哈希表,有键列表,或者关联数组。以“{”开始,以“}”结束,是“名称/值”对的集合。名称和值中间用“:”隔开。多个“名称/值”对之间用“,”隔开。
    • 数组: 值的有序列表。在大部分语言中,它被理解为数组。以“[”开始,以“]”结束,中间是数据。数据以“,”分隔。
    • JSON中的数据类型:字符串、数值、BOOL、对象、数组。
  • JSON示例
  • JSON数据结构的功能
    • 数据交换
    • 内容管理  
    • 配置文件

4、XML与JSON两种数据结构的优缺点

  • XML优缺点
    • 优点:

      • 格式统一,符合标准。
      • 容易与其他系统进行远程交互, 数据共享比较方便。
    • 
缺点:
      • XML文件格式文件庞大,格式复杂, 传输占用带宽。

      • 服务器端和客户端都需要花费大量代码来解析XML,不论服务器端还是客户端都使代码变的异常复杂和不容易维护。

      • 客户端不同浏览器之间解析XML的方式不一致,需要重复编写很多代码。

      • 服务器端和客户端解析XML花费资源和时间。
  • JSON优缺点
    • 优点:
      • 
 数据格式比较简单,易于读写,格式都是压缩的,占用带宽小。
      • 
易于解析这种语言。
      • 支持多种语言,包括ActionScript,C,C#,ColdFusion,Java,JavaScript,Perl,PHP,Python,Ruby等语言服务器端语言,便于服务器端的解析。

      • 因为JSON格式能够直接为服务器端代码使用,大大简化了服务器端和客户端的代码开发量,但是完成的任务不变,且易于维护。
    • 

缺点:

      • 没有XML格式这么推广的深入人心和使用广泛,没有XML那么通用性。

      • JSON格式目前在Web Service中推广还属于初级阶段 。

 

5、SAX解析XML文件

  解析的XML文件

  StudentInformation_XML.txt

复制代码
 1 <students>
 2     <student>
 3         <name>小暖心</name>
 4         <gender>女</gender>
 5         <age>18</age>
 6         <hobby>傲然</hobby>
 7     </student>
 8     <student>
 9         <name>MBBoy</name>
10         <gender>男</gender>
11         <age>20</age>
12         <hobby>借牙签</hobby>
13     </student>
14     <student>
15         <name>海</name>
16         <gender>男</gender>
17         <age>16</age>
18         <hobby>助人为乐</hobby>
19     </student>
20     <student>
21         <name>-1</name>
22         <gender>男</gender>
23         <age>69</age>
24         <hobby>芳芳女神</hobby>
25     </student>
26     <student>
27         <name>yyp</name>
28         <gender>女</gender>
29         <age>18</age>
30         <hobby>学习</hobby>
31     </student>
32 </students>
复制代码

 

  

SAX:Simple API for XML 。 基于事件驱动的解析方式,逐行解析数据(采用协议回调机制)

  • 核心类:NSXMLParser是iOS自带的XML解析类,采用SAX方式解析数据。
  • 解析过程有NSXMLParserDelegate协议方法回调
  • 解析过程:开始标签->取值->结束标签->取值

  使用NSXMLParse要先创建它,设置各种属性,主要用到一下几个方法:
      

  

   

  SAM解析XML数据步骤

复制代码
 1 #pragma mark - sax解析XML文件
 2 - (IBAction)saxParserActionXMLDocument:(UIButton *)sender {
 3     // 1.获取文件路径
 4     NSString *filePath = [[NSBundle mainBundle] pathForResource:@"StudentInformation_XML" ofType:@"txt"];
 5     // 2.将文件转换成NSData类型的对象
 6     NSData *data = [NSData dataWithContentsOfFile:filePath];
 7 //    NSLog(@"%@",data);
 8     // 3.设置SAX解析,并关联相关的XML文件
 9     NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
10     // 4.设置代理
11     parser.delegate = self;
12     // 5.开始解析
13     [parser parse];
14 }
15 
16 #pragma mark - NSXMLParserDelegate的协议方法
17 #pragma mark - 1.文档解析
18 - (void)parserDidStartDocument:(NSXMLParser *)parser {
19     // 数组初始化
20     self.dataArray = [NSMutableArray array];
21 }
22 
23 #pragma mark - 2.开始标签解析
24 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict {
25     // 根据需求需要的标签去获取相关的数据
26     if ([elementName isEqualToString:@"student"]) {
27         Student *student = [[Student alloc] init];
28         // 在这里不需要赋值
29         // 将数据对象添加到数组中
30         [self.dataArray addObject:student];
31     }
32     // 将当前的标签值传给currentElement属性
33     self.currentElement = elementName;
34 }
35 
36 #pragma mark - 3.解析标签中的内容,给对象赋值
37 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
38     // 从数组中取出相关的student对象,每次从数组中去最后一个元素,保证每次取出的对象都是刚刚存入的对象
39     Student *student = [self.dataArray lastObject];
40     // KVC赋值
41     [student setValue:string forKey:self.currentElement];
42 }
43 
44 #pragma mark - 4.结束标签
45 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
46     self.currentElement = nil;
47 }
48 
49 #pragma mark - 5.结束文档解析
50 - (void)parserDidEndDocument:(NSXMLParser *)parser {
51     // 打印校验
52     for (Student *student in self.dataArray) {
53         NSLog(@"name = %@, gender = %@, age = %ld, hobby = %@", student.name, student.gender, student.age, student.hobby);
54     }
55 }
56 
57 #pragma mark - 6.查看相关的错误处理
58 - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
59     NSLog(@"错误信息error = %@", parseError);
60 }
复制代码

6、DOM解析XML文件(第三方类:GDataXMLNote.h/m)

DOM:Document Object Model(文档对象模型)。DOM方式解析XML时,读入整个XML文档并构建一个驻留内存的树结构(节点树),通过遍历树结构可以检索任意XML节点,读取它的属性和值。而且通常情况下,可以借助XPath,直接查询XML节点。

  • 采用DOM方式解析数据
  • iOS中包含一个C语言的动态链接库libxml2.dylib(xcode7以后改为libxml2.tbd),解析速度比NSXMLParser快。
  • GDataXMLNode是Google提供的开源XML解析类,对libxml2.tbd进行了Objective-C的封装,能对较小或中等的xml文档进行读写操作且支持XPath语法。

  GDataXMLElement类的用到的属性和方法
  

  GDataXMLNote解析XML文件步骤

  1. 获取GDataXMLNode.h/m文件,将GDataXMLNode.h/m文件添加到工程中。
  2. 向工程中增加“libxml2.dylib”动态库。


  3. 导入"GDataXMLNode.h"文件到头文件中,此时编译失败,然后在工程的"Build Settings"页中找到"Header Search Path"项,添加"/usr/include/libxml2"。在"Other Linker Flags"项,添加"-lxml2"


  4. 此时编译报错,GDataXMLNote是非ARC文件,运行在ARC环境下会报错,按如下步骤,在Compile Source里找到刚引入的GDataXMLNote.m文件,添加"-fno-objc-arc"
复制代码
 1 #pragma mark - ---------------------------------------------
 2 #pragma mark - DOM解析XML文件
 3 - (IBAction)domParserActionXMLDocument:(UIButton *)sender {
 4     // 1.引入libxml2.tbd动态库
 5     // 2.引入第三方GDataXMLNode
 6     // 3.获取文件路径
 7     NSString *filePath = [[NSBundle mainBundle] pathForResource:@"StudentInformation_XML" ofType:@"txt"];
 8     // 4.根据路径获取NSData类型的数据
 9     NSData *data = [NSData dataWithContentsOfFile:filePath];
10     // 4.5 初始化数组
11     self.dataArray = [NSMutableArray array];
12     // 5.设置DOM解析,创建GDataXMLDocument对象,此时XML文件内所有的节点以树的形式存在GDataXMLDocument
13     GDataXMLDocument *document = [[GDataXMLDocument alloc] initWithData:data options:0 error:nil];
14     // 6.获取根节点,根节点里面包含了XML的所有信息
15     GDataXMLElement *rootElement = document.rootElement;
16     // 7.遍历获取相对应的子节点(student)
17     for (GDataXMLElement *studentElement in rootElement.children) {
18         Student *student = [[Student alloc] init];
19         // 遍历子节点(student)的子节点(name,gender,age,hobby)
20         for (GDataXMLElement *element in studentElement.children) {
21             NSLog(@"%@",element);
22             // KVC:根据标签给student对象赋值
23             // element.name 标签的名字
24             // element.stringValue 标签的值
25             [student setValue:element.stringValue forKey:element.name];
26         }
27         // 将student对象添加到数组中
28         [self.dataArray addObject:student];
29     }
30     // 遍历检验
31     for (Student *student in self.dataArray) {
32         NSLog(@"name = %@, gender = %@, age = %ld, hobby = %@", student.name, student.gender, student.age, student.hobby);
33     }
34 }
复制代码

 


  解析的JSON文件  

  StudentInformation_json.txt

复制代码
 1 [
 2     {
 3         "name":"凯凯",
 4         "gender":"男",
 5         "age":"18",
 6         "hobby":"PS"
 7     },
 8     {
 9         "name":"YH",
10         "gender":"男",
11         "age":"20",
12         "hobby":"女"
13     },
14     {
15         "name":"ZF",
16         "gender":"男",
17         "age":"20",
18         "hobby":"玩毛"
19     },
20     {
21         "name":"小明",
22         "gender":"男",
23         "age":"22",
24         "hobby":"滚出去"
25     },
26     {
27         "name":"淮予",
28         "gender":"女",
29         "age":"21",
30         "hobby":"小暖心"
31     }
32 ]
复制代码

 

7、系统自带Foundation框架解析JSON数据

  NSJSONSerialization  里面包含了两个方法来通过不同数据形式解析JSON数据。

    

复制代码
 1 #pragma mark - ---------------------------------------------------
 2 #pragma mark - 系统自带Foundation框架解析JSON数据
 3 - (IBAction)foundationParserActionJSONDocument:(UIButton *)sender {
 4     // 1.获取文件路径
 5     NSString *filePath = [[NSBundle mainBundle] pathForResource:@"StudentInformation_json" ofType:@"txt"];
 6     // 2.根据路径获取NSData类型的数据
 7     NSData *data = [NSData dataWithContentsOfFile:filePath];
 8     // 2.5 初始化数组
 9     self.dataArray = [NSMutableArray array];
10     // 3.解析
11     NSArray *resultArray = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
12     // 4.遍历数组,使用KVC给Student对象赋值
13     for (NSDictionary *dict in resultArray) {
14         Student *student = [[Student alloc] init];
15         [student setValuesForKeysWithDictionary:dict];
16         [self.dataArray addObject:student];
17     }
18     // 遍历检验
19     for (Student *student in self.dataArray) {
20         NSLog(@"name = %@, gender = %@, age = %ld, hobby = %@", student.name, student.gender, student.age, student.hobby);
21     }
22 }
复制代码

 

8、使用第三方类JSONKit来解析JSON数据

  引入JSONKit.h/m文件,并设置非ARC文件在ARC环境下运行。

  

复制代码
 1  1 #pragma mark - -------------------------------------------------
 2  2 #pragma mark - 使用第三方类JSONKit来解析JSON数据
 3  3 - (IBAction)jsonkitParserActionJSONDocument:(UIButton *)sender {
 4  4     // 1.引入第三方类  -- 设置 非arc文件在arc环境下运行
 5  5     // 2.获取文件路径
 6  6     NSString *filePath = [[NSBundle mainBundle] pathForResource:@"StudentInformation_json" ofType:@"txt"];
 7  7     // 3.根据路径获取NSData类型的数据
 8  8     NSData *data = [NSData dataWithContentsOfFile:filePath];
 9  9     // 3.5初始化数组
10 10     self.dataArray = [NSMutableArray array];
11 11     // 4. 解析   与NSJSONSerialization解析的唯一差别
12 12     NSArray *resultArray = [data objectFromJSONData];
13 13     // 5.遍历数组,使用KVC给Student对象赋值
14 14     for (NSDictionary *dict in resultArray) {
15 15         Student *student = [[Student alloc] init];
16 16         [student setValuesForKeysWithDictionary:dict];
17 17         [self.dataArray addObject:student];
18 18     }
19 19     // 遍历检验
20 20     for (Student *student in self.dataArray) {
21 21         NSLog(@"name = %@, gender = %@, age = %ld, hobby = %@", student.name, student.gender, student.age, student.hobby);
22 22     }
23 23 }
复制代码

总结:

  1.数据解析:从某种格式的数据中提取自己所需要的数据

  2.主流的数据交换格式有两种:XML和JSON

  3.XML解析分为两种:SAX解析和DOM解析

  4.XML解析工具:NSXMLParser、GDataXMLNode、TochXML和KissXML等  

  5.JSON解析工具:JSONKit、NSJSONSerialization、TouchJSON和SBJSON等,其中NSJSONSerialization是系统提供的解析类,其解析效率是最高的

  

 

posted @ 2016-05-18 20:26  维他命11  阅读(1742)  评论(0编辑  收藏  举报