读写iOS XML文件

读写XML文档,目前流行的两种模式:SAX和DOM。

1.SAX是一种基于事件驱动的解析模式。解析XML的时候,程序从上到下读取XML文档,如果遇到开始标签、结束标签、属性等,就会触发相应的事件。

优点:解析速度快,iOS重点推荐使用SAX模式解析

缺点:只能读取XML文档,不能写入XML文档

2.DOM模式是将XML文档作为一颗树状结构进行分析,提供获取节点的内容,以及相关属性,或是新增、删除和修改节点的内容。XML解析器在加载XML文件以后,DOM将XML文件的元素视为一个树状结构的节点,一次性读入到内存中。

优点:能够修改XML文档

缺点:如果文档比较大,解析速度就会变慢

NSXML是iOS SDK自带的,也是苹果默认的解析框架,采用SAX模式解析,它是SAX解析模式的代表。本文主要介绍采用NSXML解析XML文件。

采用NSXML解析XML文件

NSXML框架中的核心是NSXMLParser和它的代理NSXMLParserDelegate,NSXMLParserDelegate中的常用方法有:

// 在文档开始的时候触发- (void)parserDidStartDocument:(NSXMLParser*)parser;// 在文档出错的时候触发,该方法一般在调试阶段使用,实际发布时意义不大- (void)parser:(NSXMLParser*)parser parseErrorOccurred:(NSError*)parseError;// 遇到一个开始标签时触发,其中namespaceURI部分是命名空间,qualifiedName是限定名,attributes是字典类型的属性集合- (void)parser:(NSXMLParser*)parser didStartElement:(NSString*)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString*)qName attributes:(NSDictionary*)attributeDict;// 遇到字符串时触发- (void)parser:(NSXMLParser*)parser foundCharacters:(NSString*)string;// 遇到结束标签时触发- (void)parser:(NSXMLParser*)parser didEndElement:(NSString*)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString*)qName;// 遇到文档结束时触发- (void)parserDidEndDocument:(NSXMLParser*)parser;

代码演示解析XML文件

Notes.xml文件如下:

2015-10-20早上7点钟起床到实验室xiaolou2015-10-21学习iOS开发xiaolou2015-10-22学习iOS开发之解析XML文件xiaolou2015-10-23采用NSXML解析XML文件xiaolou2015-10-24解析速度快,iOS重点推荐使用SAX模式解析xiaolou2015-10-25该投简历了,希望能找个好工作xiaolou

新建一个类NotesXMLParser,继承自NSObject,遵守委托协议NSXMLParserDelegate,并拥有相关属性与方法。

NotesXMLParser.h文件:

#import@interfaceNotesXMLParser:NSObject// 解析出的数据内部是字典类型@property(strong,nonatomic)NSMutableArray*notes;// 当前标签的名字@property(strong,nonatomic)NSString*currentTagName;// 开始解析- (void)start;@end

注:定义currentTagName属性的目的是:在触发开始标签方法和结束标签方法 期间临时存储正在解析的元素名,在方法(parser:foundCharacters:)触发时,能够知道目前解析器处于哪个元素之中

NotesXMLParser.m文件中实现start方法:

- (void)start {NSString*path = [[NSBundlemainBundle] pathForResource:@"Notes"ofType:@"xml"];NSURL*url = [NSURLfileURLWithPath:path];// 开始解析XMLNSXMLParser*parser = [[NSXMLParseralloc] initWithContentsOfURL:url];    parser.delegate=self;    [parser parse];NSLog(@"解析完成。。。");}

注:NSXMLParser是解析类,它有3个构造方法

1)- (instancetype)initWithContentsOfURL:(NSURL)url;

2)- (instancetype)initWithData:(NSData)data;

3) - (instancetype)initWithStream:(NSInputStream *)stream;

实现NSXMLParserDelegate代理方法:

// 文档开始的时候触发- (void)parserDidStartDocument:(NSXMLParser*)parser {// 此方法只在解析开始时触发一次,因此可在这个方法中初始化解析过程中用到的一些成员变量_notes = [NSMutableArraynew];}// 文档出错的时候触发- (void)parser:(NSXMLParser*)parser parseErrorOccurred:(NSError*)parseError {NSLog(@"%@", parseError);}// 遇到一个开始标签的时候触发- (void)parser:(NSXMLParser*)parser didStartElement:(NSString*)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString*)qName attributes:(NSDictionary*)attributeDict {// elementName是正在解析的元素的名字_currentTagName = elementName;// 如果元素名字为Note,取出它的属性idif([_currentTagName isEqualToString:@"Note"]) {// 属性在attributeDict参数中传递过来,它是一个字典类型,其中的键的名字就是属性的名字,值是属性的值NSString*_id= [attributeDict objectForKey:@"id"];NSMutableDictionary*dict = [NSMutableDictionarynew];        [dict setObject:_idforKey:@"id"];        [_notes addObject:dict];    }}// 遇到字符串时候触发,该方法是解析元素文本内容主要场所- (void)parser:(NSXMLParser*)parser foundCharacters:(NSString*)string {// 剔除回车和空格// stringByTrimmingCharactersInSet:方法是剔除字符方法// [NSCharacterSet whitespaceAndNewlineCharacterSet]指定字符集为换行符和回车符string = [string stringByTrimmingCharactersInSet:[NSCharacterSetwhitespaceAndNewlineCharacterSet]];if([string isEqualToString:@""]) {return;    }NSMutableDictionary*dict = [_notes lastObject];if([_currentTagName isEqualToString:@"CDate"] && dict) {        [dict setObject:string forKey:@"CDate"];    }if([_currentTagName isEqualToString:@"Content"] && dict) {        [dict setObject:string forKey:@"Content"];    }if([_currentTagName isEqualToString:@"UserID"] && dict) {        [dict setObject:string forKey:@"UserID"];    }}// 遇到结束标签时触发,在该方法中主要是清理刚刚解析完成的元素产生的影响,以便于不影响接下来的解析- (void)parser:(NSXMLParser*)parser didEndElement:(NSString*)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString*)qName {// 清理刚才解析的元素的名字,以便于记录接下来解析的元素的名字self.currentTagName=nil;}// 遇到文档结束时触发- (void)parserDidEndDocument:(NSXMLParser*)parser {// 使用通知机制将数据通过广播通知投送回表示层[[NSNotificationCenterdefaultCenter] postNotificationName:@"reloadViewNotification"object:self.notesuserInfo:nil];// 解析完成,清理成员变量self.notes=nil;}

ViewController.m文件:

#import"ViewController.h"#import"NotesXMLParser.h"@interfaceViewController() {UITableView*_tableView;}//保存数据列表@property(nonatomic,strong)NSMutableArray* listData;@end@implementationViewController- (void)viewDidLoad {    [superviewDidLoad];    _tableView = [[UITableViewalloc] initWithFrame:self.view.boundsstyle:UITableViewStylePlain];    _tableView.dataSource=self;    [self.viewaddSubview:_tableView];// 注册一个通知,这样ViewController才能在解析完成后接收到投送回来的通知// 一旦投送成功就会触发reloadView:方法,在该方法中取出数据,并重新加载表示图[[NSNotificationCenterdefaultCenter] addObserver:selfselector:@selector(reloadView:)                                        name:@"reloadViewNotification"object:nil];    NotesXMLParser *parser = [NotesXMLParser new];// 开始解析[parser start];}- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView {return1;}- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section {returnself.listData.count;}- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {staticNSString*ID =@"cell";UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:ID];if(!cell) {        cell = [[UITableViewCellalloc] initWithStyle:UITableViewCellStyleSubtitlereuseIdentifier:ID];    }NSMutableDictionary*  dict =self.listData[indexPath.row];    cell.textLabel.text= [dict objectForKey:@"Content"];    cell.detailTextLabel.text= [dict objectForKey:@"CDate"];returncell;}#pragma mark - 处理通知- (void)reloadView:(NSNotification*)notification {// 在该方法中取出数据,并重新加载表示图NSMutableArray*resList = [notification object];self.listData= resList;    [_tableView reloadData];}@end

转载请保留原文地址:http://www.jianshu.com/p/871830fc9945

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容