ios之xml解析
iOS ——XML数据结构及其两种解析数据的方式SAX 、DOM
2015年09月26日 16:09:58 GreenWitch 阅读数:1189
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语法中的某部分,如果符合就会触发事件