#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