XML解析整理
微软 和 IBM 曾经全力推荐XML
XML目前应用场景
XMPP——即时通讯,KissXML
RSS目前还有少量的企业在使用
开源的WebServices,例如天气预报等
如果设计好XML的接口,XML的解析并不会太复杂
移动开发中绝大多数还是使用JSON
如果自己开发,或者公司后台接口,最好使用JSON
XML
XML 是一种标记语言,很类似 HTML
XML 的设计宗旨是传输和存储数据,而非显示数据
NSXMLParser解析过程
实例化NSXMLParser,传入从服务器接收的XML数据
定义解析器代理
解析器解析
通过解析代理方法完成XML数据的解析
NSXMLParser解析代理方法
// 1. 开始解析XML文档
- (void)parserDidStartDocument:
// 2. 开始解析某个元素,会遍历整个XML,识别元素节点名称
- (void)parser:didStartElement:namespaceURI:qualifiedName:attributes:
// 3. 文本节点,得到文本节点里存储的信息数据,对于大数据可能会接收多次!为了节约内存开销
- (void)parser:foundCharacters:
// 4. 结束某个节点,存储从parser:foundCharacters:方法中获取到的信息
- (void)parser:didEndElement:namespaceURI:qualifiedName:
注意:在解析过程中,2、3、4三个方法会不停的重复执行,直到遍历完成为止
// 5. 解析XML文档结束
- (void)parserDidEndDocument:
// 6. 解析出错
-(void)parser:parseErrorOccurred:
下面是代码详细步骤
#import <Foundation/Foundation.h>
@interface Video : NSObject
@property (nonatomic, copy) NSNumber *videoId;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSNumber *length;
@property (nonatomic, copy) NSString *videoURL;
@property (nonatomic, copy) NSString *imageURL;
@property (nonatomic, copy) NSString *desc;
- (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)videoWithDict:(NSDictionary *)dict;
@end
#import "PLMXMLViewController.h"
#import "Video.h"
@interface PLMXMLViewController () <NSXMLParserDelegate>
@property (nonatomic, strong) NSMutableArray *videoList;
@property (nonatomic, strong) NSMutableString *elementM;
@property (nonatomic, strong) Video *currentVideo;
@end
@implementation PLMXMLViewController
- (NSMutableArray *)videoList
{
if (!_videoList) _videoList = [NSMutableArray array];
return _videoList;
}
- (NSMutableString *)elementM
{
if (!_elementM) _elementM = [NSMutableString string];
return _elementM;
}
/** 加载数据,重写父类的方法 */
- (void)loadData
{
// 1. url确定资源
NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/videos.xml"];
// 2. request建立请求
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 3. 发送异步请求,新建数据处理队列,待数据处理完成后,再更新UI
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// 1> 实例化XML解析器
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
// 2> 设置解析器的代理
parser.delegate = self;
// 3> 开始解析
[parser parse];
}];
}
#pragma mark - XML解析代理方法
// 1. 开始解析文档
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
// 为了避免重复刷新数据,可以清空数组
[self.videoList removeAllObjects];
}
// 2,3,4三个方法会循环被调用
// 2. 开始一个元素(节点)<xxx>
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:@"video"]) {
// 创建新的video对象
self.currentVideo = [[Video alloc] init];
// 使用KVC赋值
[self.currentVideo setValue:attributeDict[@"videoId"] forKeyPath:@"videoId"];
}
// 在开始第3个方法前,清空字符串内容
[self.elementM setString:@""];
}
// 3. 发现字符(节点中间内容)
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
[self.elementM appendString:string];
}
// 4. 结束节点</xxx>
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:@"video"]) {
// 将当前正在解析的节点添加到数组
[self.videoList addObject:self.currentVideo];
} else if (![elementName isEqualToString:@"videos"]) {
[self.currentVideo setValue:self.elementM forKeyPath:elementName];
}
}
// 5. 结束文档解析
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
NSLog(@"结束文档解析 %@", self.videoList);
NSLog(@"%@", [NSThread currentThread]);
dispatch_async(dispatch_get_main_queue(), ^{
// 将XML解析结果,赋值给self.dataList
// 调用了父类的setDataList方法,自动实现刷新表格!
self.dataList = self.videoList;
});
}
// 6. 在处理网络数据时,千万不要忘记出错处理
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
NSLog(@"错误 %@", parseError);
}
@end