ios网络学习------8 xml格式数据的请求处理 用代码块封装

时间:2021-12-06 07:59:56
#pragma mark 载入xml
- (void)loadXML
{
//获取网络数据。
NSLog(@"load xml");
//从webserver载入数据
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];
}];
}


<pre name="code" class="objc">#import <Foundation/Foundation.h>

//代理方法中须要与调用者交互的方法:
// 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


<pre name="code" class="objc">#import "MyXMLParser.h"

@interface MyXMLParser() <NSXMLParserDelegate>
{
//记录块代码的成员变量
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