#pragma mark 載入xml- (void)loadXML{ //擷取網路資料。 NSLog(@"load xml"); //從web伺服器載入資料 NSString *str = @"http://www.baidu.com?format=xml"; //這裡是亂寫的 //1簡曆NSURL NSURL *url = [NSURL URLWithString:str]; //2建立NSURLRequest NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:2.0f]; //3建立NSURLConnect的同步方法載入資料 NSURLResponse *response = nil; NSError *error = nil; //同步載入資料 NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; MyXMLParser *myParser = [[MyXMLParser alloc]init]; //懶載入執行個體化資料 if (self.dataList == nil) { self.dataList = [NSMutableArray array]; }else{ [self.dataList removeAllObjects]; } //解析資料 [myParser xmlParserWithData:data StartName:@"video" startElement:^( NSDictionary *dict) { //1 執行個體化currentvideo self.currentVideo = [[Video alloc]init]; //2 設定videoid self.currentVideo.videoId = [dict[@"videoId"]integerValue]; } endElement:^(NSString *elementName, NSString *result) { if ([elementName isEqualToString:@"name"]) { self.currentVideo.name = result; }else if ([elementName isEqualToString:@"length"]){ self.currentVideo.length = [result integerValue]; }else if ([elementName isEqualToString:@"videoURL"]){ self.currentVideo.videoId = [result integerValue]; }else if ([elementName isEqualToString:@"imageURL"]){ self.currentVideo.imageURL = result; }else if ([elementName isEqualToString:@"desc"]){ self.currentVideo.desc = result; }else if ([elementName isEqualToString:@"teacher"]){ self.currentVideo.teacher = result; }else if ([elementName isEqualToString:@"video"]){ [self.dataList addObject:self.currentVideo]; } } finishedParser:^{ self.currentVideo = nil; [self.tableView reloadData]; //重新整理表格式資料 } errorParser:^{ NSLog(@"解析出現錯誤"); //清空臨時資料 self.currentVideo = nil; //清空數組 [self.dataList removeAllObjects]; }];}
#import //代理方法中需要與調用者互動的方法: // 2 互動元素: elementname attributeDict // 4 互動的元素: elementname 中轉的字串 //5 僅通知即可 //6 僅通知即可//定義塊代碼:typedef void(^startElementBlock)(NSDictionary *dict);typedef void(^endElementBlock)(NSString *elementName, NSString *result);typedef void(^xmlParserNotificationBlock)();@interface MyXMLParser : NSObject//定義解析方法/* data xml資料 startname 開始的節點名稱 startElement 開始節點方法 endElement 結束節點方法 finishedparser 文檔解析結束。 errorParse 文檔解析出錯。*/-(void)xmlParserWithData:(NSData *)data StartName:(NSString *)startName startElement:(startElementBlock)startElement endElement:(endElementBlock)endElement finishedParser:(xmlParserNotificationBlock)finishedParser errorParser:(xmlParserNotificationBlock)errorParser;@end
#import "MyXMLParser.h"@interface MyXMLParser() { //記錄塊代碼的成員變數 startElementBlock _startElementBlock; endElementBlock _endElementBlock; xmlParserNotificationBlock _finishedBlock; xmlParserNotificationBlock _errorBlock;}//開始節點名稱,列如:video 如果檢測到此名稱, 需要執行個體化對象@property (strong, nonatomic)NSString *startElementName;//中轉字串@property (strong, nonatomic) NSMutableString *elementString;@end@implementation MyXMLParser//在這個方法裡面實現xml的解析。/* data xml資料 startname 開始的節點名稱 startElement 開始節點方法 endElement 結束節點方法 finishedparser 文檔解析結束。 errorParse 文檔解析出錯。 */- (void)xmlParserWithData:(NSData *)data StartName:(NSString *)startName startElement:(startElementBlock)startElement endElement:(endElementBlock)endElement finishedParser:(xmlParserNotificationBlock)finishedParser errorParser:(xmlParserNotificationBlock)errorParser{ self.startElementName = startName; //記錄塊代碼 _startElementBlock = startElement; _endElementBlock = endElement; _finishedBlock = finishedParser; _errorBlock = errorParser; //定義解析器並且開始解析 NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data]; [parser setDelegate:self]; //設定代理 //開始解析 [parser parse]; //這個方法會調用下面的幾個方法來實現。}#pragma mark - XML解析器代理方法//所謂需要與外界互動,表示需要與調用發打交道,通知調用放執行某些操作。//1開始解析文檔,初始化資料,也不需要與外部互動。- (void)parserDidStartDocument:(NSXMLParser *)parser{ //執行個體化中裝字串 if (self.elementString == nil) { self.elementString = [NSMutableString string]; }}//2開始解析元素(元素的頭部video, 需要執行個體化對象, attributedict需要設定屬性)//需要與外部互動//互動的元素: elementName attributeDict- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{ if ([elementName isEqualToString:self.startElementName]) { //開始部分代碼 _startElementBlock(attributeDict); } //開始迴圈執行第三個方法前,清空中轉字串 [self.elementString setString:@""];}//3發現元素字串(拼接字串,不需要和外部互動)- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{ [self.elementString appendString:string];}//4結束元素解析,根據elementname和第三步的拼接內容,確定對象屬性,需要與外部互動//互動的元素: elementname 中轉的字串- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{ NSString *result = [NSString stringWithString:self.elementString]; _endElementBlock(elementName, result);}//5解析文檔結束,通常需要調用放重新整理資料。//互動的元素: 僅通知即可- (void)parserDidEndDocument:(NSXMLParser *)parser{ [self.elementString setString:@""]; _finishedBlock();}//解析出錯,通知調用方解析出錯(需要與外界互動)。//互動的元素: 僅通知即可。- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{ NSLog(@"解析出錯"); [self.elementString setString:@""]; //帶一個nserror回去會更好。 _errorBlock();}@end