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 数据结构的语法 

声明: 

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

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

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

pastedGraphic.png 

pastedGraphic_1.png

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个的时候,1213时候2425的时候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语法中的某部分,如果符合就会触发事件

 

posted @ 2019-02-11 17:45  sundaysios  阅读(201)  评论(0编辑  收藏  举报