在ios 中解析xml 的方法有很多种
1.苹果原生
NSXMLParser:SAX方式解析,使用简单
2.第三方框架
libxml2:纯c语言,默认包含在ios sdk中,同时支持DOM 和 SAX 方式解析
GDataXML : DOM方式解析,由谷歌开发,基于libxml2
xml 解析建议方式:
大文件选用:NSXMLParser 或者 libxml2
小文件选用:GDataXML
xml解析:
SAX方式解析:
从上往下,一点一点解析,性能比较好,也是苹果推荐使用的。
DOM方式解析
一次性将xml文档以树形结构读入内存,内存消耗比较大。适用于比较小的xml文件解析。在ios 开发中默认是不支持这种方式的解析。但是有一些第三方框架实现了这个方式,
KissXML & GData 都是采用DOM解析。
// // ViewController.m // 04-xml解析 // // Created by jerry on 15/9/28. // Copyright (c) 2015年 jerry. All rights reserved. // #import "ViewController.h" #import "Video.h" @interface ViewController ()<NSXMLParserDelegate> /*** 整个xml的数据容器*/ @property(nonatomic,strong)NSMutableArray *videos;/*** 第三步拼接字符串*/ @property(nonatomic,strong)NSMutableString *elementString; /*** 当前模型*/ @property(nonatomic,strong)Video *currentVideo; /*** 专门用来存储表格所有的数据,也就是表格数据源*/ @property(nonatomic,strong)NSMutableArray *dataList; @end@implementation ViewController @synthesize videos = _videos; - (void)setDataList:(NSMutableArray *)dataList {_dataList = dataList;// 只要重新赋值 就要刷新 [self.tableView reloadData];// 隐藏刷新控件 [self.refreshControl endRefreshing]; } /*** 懒加载 初始化 自定义属性*/ -(NSMutableArray *)videos {if (_videos == nil) {_videos = [NSMutableArray array];}return _videos; } /*** 懒加载 初始化 自定义属性** @return <#return value description#>*/ - (NSMutableString *)elementString {if (_elementString == nil) {_elementString = [NSMutableString string];}return _elementString; } //- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // [self loadData]; //} -(void)loadView {[super loadView];[self loadData]; } /*** 加载xml 数据* 从第2步到第4步,可以拿到video的属性。*/ - (IBAction)loadData {// 1.urlNSURL *url = [NSURL URLWithString:@"http://127.0.0.1/videos.xml"];// 2.请求// 不采用这个请求的原因就是因为他会有缓存,每次加载会先找缓存数据,这样就会出现“幻觉”数据。// NSURLRequest *request = [NSURLRequest requestWithURL:url];// 这样的请求 可以避免缓存数据,以免数据更改了 刷新ui 的时候还是显示原来的数据。NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:2.0f];// 3.连接[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {// xml 解析// 1.实例化xml 解析器NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data];// 2.设置代理parser.delegate = self;// 3.开始解析 [parser parse];}]; } #pragma mark - 代理方法 /*** 1.打开文档 准备开始解析** @param parser <#parser description#>*/ - (void)parserDidStartDocument:(NSXMLParser *)parser {NSLog(@"打开文档");// 初始化数组容器,清空容器,便于多次加载数据 [self.videos removeAllObjects]; }/*** 2.开始节点* 新建一个video对象,设置video的属性,* @param parser <#parser description#>* @param elementName 元素名称* @param namespaceURI <#namespaceURI description#>* @param qName <#qName description#>* @param attributeDict <#attributeDict description#>*/ - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {NSLog(@"开始节点---%@---%@",elementName,attributeDict);// 如果开始节点的名称是video 就创建一个对象。if ([elementName isEqualToString:@"video"]) {self.currentVideo =[[Video alloc]init];// 设置videoidself.currentVideo.videoId = attributeDict[@"videoId"];}// 清空字符串内容 因为马上要进行第3步,开始拼接当前节点内容[self.elementString setString:@""]; } /*** 3.发现节点里面内容** @param parser <#parser description#>* @param string <#string description#>*/ - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {NSLog(@"发现节点内容---%@",string);// 开始拼接[self.elementString appendString:string]; } /*** 4.结束节点** @param parser <#parser description#>* @param elementName <#elementName description#>* @param namespaceURI <#namespaceURI description#>* @param qName <#qName description#>*/ - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {NSLog(@"结束节点---%@",elementName);if ([elementName isEqualToString:@"video"]) {// 如果结束节点是video 需要把这个对象添加到数组 [self.videos addObject:self.currentVideo];}else if (![elementName isEqualToString:@"videos"]){// 利用kvc 进行赋值。可以省略注释掉的代码的麻烦。 [self.currentVideo setValue:self.elementString forKeyPath:elementName];}// // 如果结束节点,就可以把第二步创建的对象进行赋值,设置name/length属性 // else if ([elementName isEqualToString:@"name"]) { // // 设置name 属性 // self.currentVideo.name = self.elementString; // // }else if ([elementName isEqualToString:@"length"]) // { // // 设置length属性 // // @([self.elementString integerValue]) 现将字符串转成 数字,然后再将数字专程number // self.currentVideo.length = @([self.elementString integerValue]); // // } } /*** 5.结束文档** @param parser <#parser description#>*/ - (void)parserDidEndDocument:(NSXMLParser *)parser {NSLog(@"结束文档");// xml 真正解析结束 可以在主线程更新uidispatch_async(dispatch_get_main_queue(), ^{self.dataList =self.videos;}); }- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {return self.videos.count; } - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];Video *video = self.dataList[indexPath.row];cell.textLabel.text = video.name;return cell; }@end