讀寫iOS XML檔案

weixin_34337265發表於2016-08-15

讀寫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

相關文章