您的位置:首页 > 理论基础 > 数据结构算法

iOS ——XML数据结构及其两种解析数据的方式SAX 、DOM

2015-09-26 16:09 609 查看
1.解析的基本概念

所谓解析:从事先规定好的格式中提取数据

解析的前提:提前规定好格式、数据提供方按照格式提供数据、数据获取方则按照格式获取数据。

iOS 常见的解析:XML 解析、JSON 解析

2.XML 基本概念

XML:Extensible Markup language(可扩展标记语⾔言)主流数据格式之 一,可以用来存储和传输数据。

XML 数据格式的功能:数据交换、内存管理、用作配置文件。

XML 数据结构的语法

声明:

节点使用一对标签标示。其实结束标签。

根节点是起始节点,只有一个。节点可以嵌套。

节点可以有值。存储在一对标签中。





3.SAX 解析

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

2)NSXMLParser是iOS⾃自带的XML解析类。采⽤用SAX⽅方式解析数据。

3)解析过程由NSXMLParserDelegate协议⽅方法回调

4)解析过程:开始标签->取值->结束标签->取值

代码如下:

StudentInfor_XML.txt 文件

<students>  //根节点 开始标签
<student>   //根节点的子节点, name 的父节点
<name>懒洋洋</name>  //懒洋洋 :节点的值
<age>3</age>
<gender>male</gender>
<hobby>女</hobby>
<phone>128395069078</phone>
</student>

<student>
<name>懒洋洋1</name>
<age>3</age>
<gender>male</gender>
<hobby>女</hobby>
<phone>128395069078</phone>
</student>

<student>
<name>懒洋洋2</name>
<age>3</age>
<gender>male</gender>
<hobby>男</hobby>
<phone>128395069078</phone>
</student>

</students>  //节点的结束标签


XML解析步骤:

1、实例化NSXMLParser,传入从服务器接收的XML数据

2、定义解析器代理

3、解析器解析,通过解析代理方法完成XML数据的解析。

解析XML用到的的代理方法:

1. 开始解析XML文档

- (void)parserDidStartDocument:

2. 开始解析某个元素,会遍历整个XML,识别元素节点名称,如开头

-(void)parser:didStartElement:namespaceURI:qualifiedName:attributes:

3. 文本节点,得到文本节点里存储的信息数据。 节点中的数据XXXX

- (void)parser:foundCharacters:

4. 结束某个节点 如开头

- (void)parser:didEndElement:namespaceURI:qualifiedName:

注意:在解析过程中,2、3、4三个方法会不停的重复执行,直到遍历完成为止

5.解析XML文档结束

- (void)parserDidEndDocument:

6.解析出错

-(void)parser:parseErrorOccurred:

//存放model 对象的容器
@property (nonatomic, strong) NSMutableArray * array;
//当前节点
@property (nonatomic, strong) NSString * currentElement;

#pragma mark XMLBUtton 的点击事件
- (IBAction)xmlSAXAction:(id)sender {
//  1. 获取文件路径
NSString * path = [[NSBundle mainBundle]pathForResource:@"StudentInfor_XML" ofType:@"txt"];
//    2.根据文件对象创建data 对象 (使用init 方法)
NSData * data = [[NSData alloc] initWithContentsOfFile:path];
//    3. 根据data 对象创建解析对象
NSXMLParser * xmlparser = [[NSXMLParser alloc] initWithData:data];
//    4. 设置代理
xmlparser.delegate = self;
//  5.开始解析 方法 - (BOOL)parse;
[xmlparser parse];
}

#pragma mark -  SAX 解析        SAX代理步骤---
#pragma mark - 1.开始文档解析
-(void)parserDidStartDocument:(NSXMLParser *)parser
{
//    开始文档解析的时候准备数组
//    数组里面存的是指针。
//    initWithCapacity 方法初始化 : 6 的倍数初始化。 刚开始6个。 放到7个的时候,12。13时候24。25的时候48. 减少数组在内存中的迁移。
_array = [[NSMutableArray alloc] initWithCapacity:6];
}

#pragma mark 2. 开始标签解析
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
//    记录当前标签
_currentElement = elementName;
//    根据标签student 建立model
if ([elementName isEqualToString: @"student"]) {
//        此时添加到数组中的 student对象为空。解析出来时再添加对象的值
Student * student = [Student new];
[_array addObject:student];
}
}
#pragma mark 3.获取标签内容
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
//获取数组最后一个元素 (获取数组中的随后一个元素,给最后一个元素赋值。如果是第一个元素赋值,会覆盖)
Student * student = [_array lastObject];
//    KVC 赋值
[student setValue:string forKey:_currentElement];
}

#pragma mark - 4. 结束标签解析
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
NSLog(@"结束标签解析");
//    当前存储点置为空, 不影响下次判断
_currentElement = nil;
}
#pragma mark 5.结束文档解析
-(void)parserDidEndDocument:(NSXMLParser *)parser
{
NSLog(@"结束文档解析");
//    检验数据
for (Student * student  in _array) {
NSLog(@"%@",student);
}
}
#pragma mark 6. 错误处理
-(void) parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
NSLog(@"写错了,错误为%@",parseError);
}


总结:先开始文档解析,再开始标签解析。解析标签时,一个student 标签需要全部解析完在解析下一个,所以需要每次取出数组中Student * student = [_array lastObject]; 赋上解析的数据。

4.使用DOM 工具解析XML

DOM 解析

1)DOM:Document Object Model(⽂文档对象模型)。解析时需要

将XML⽂文件整体读⼊入,并重点内容且将XML结构化成树状,使⽤用时再通过树 状结构读取相关数据

2)GDataXMLNode是Google提供的开源XML解析类,对

libxml2.dylib进⾏行了Objective-C的封装

代码:

#pragma mark - XML DOM 解析 --

- (IBAction)xmlDOMAction:(id)sender
{
//    1. 获取文件路径
//    获取应用程序包
NSBundle * bundle = [NSBundle mainBundle];
//    通过包获取路径
NSString * path = [bundle pathForResource:@"StudentInfor_XML" ofType:@"txt"];
//    2. 根据文件路径获取data 对象 (使用遍历构造器方法)
NSData * data = [NSData dataWithContentsOfFile:path];
//    3. 根据datda 对象创建解析对象
GDataXMLDocument * document = [[GDataXMLDocument alloc] initWithData:data options:0 error:nil];
//    4.获取根节点 (本题中<students>)
GDataXMLElement * rootElement = [document rootElement];
//   初始化数组,开辟空间(开辟6个指针大小的空间,给array)
_array = [[NSMutableArray alloc]initWithCapacity:6];
// 遍历根节点的孩子节点 ,获取每个孩子节点(<student>)
for (GDataXMLElement * subEement in rootElement.children) {
//创建对象
Student * student = [Student new];
for (GDataXMLElement * element in subEement.children) {
//遍历 孩子节点的孩子节点,获取每个孩子节点的值。并给student 的各个属性赋值。
[student setValue:element.stringValue forKey:element.name];
}
//        添加到数组中
[_array addObject:student];
}
//    校验
for (Student * student  in _array) {
NSLog(@"%@",student);
}
}


总结:iOS 中对XML 文件的解析方法有两种:DOM 、SAX

比较:

1.SAX方法可以使用iOS SDK中的NSXMLParser,DOM方法可以使用GOOGLE提供的GDataXML。

2、SAX(SimpleAPI for XML)

只能读,不能修改,只能顺序访问,适合解析大型XML,解析速度快

常应用于处理大量数据的XML,实现异构系统的数据访问,实现跨平台

从文档的开始通过每一节点移动,定位一个特定的节点

3、DOM(DocumentObject Model)

不仅能读,还能修改,而且能够实现随机访问,缺点是解析速度慢,适合解析小型文档.方便操作.

在内存中生成节点树操作代价昂贵。

详细理解:

DOM将整个xml看成是一个树状的结构,在解析的时候,会将整个xml文件加载到我们的内存当中,然后通过DOM提供的API来对我们的xml数据进行解析,这种方式解析xml非常的方便,并且我们可以通过某个节点访问到其兄弟或者是父类、子类节点。

不好的地方就是,其会将整个xml文档加载到内存中,这样会大大的占用我们的内存资源,对于手机来说,内存资源是非常非常宝贵的。

SAX相对于DOM 速度慢但是占用内存小,非常适合用于移动设备。 SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: