XML有两种解析方式:
- SAX解析
SAX:SimpleAPIfor XML。基于事件驱动的解析方式,逐行解析数据。(采用协议回调机制)
- DOM解析
DOM:DocumentObjectModel(文档对象模型)。解析时需要将XML文件整体读入,并且将XML结构化成树状,使用时再通过树状结构读取相关数据
NSXMLParser是iOS自带的XML解析类。采用SAX方式解析数据, 解析过程由NSXMLParserDelegate协议方法回调
NSXMLParser
NSXMLParser 由苹果SDK提供
在项目中添加协议NSXMLParserDelegate
常用的有3个方法
// 当开始处理某个元素节点时触发该方法
- (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;
TouchXML
- TouchXml类库下载链接 —– 注意需要改为mrc 即-fno-objc-arc
- 导入 CXMLDocument.h
- 开始解析
code案例
此处网络请求使用第三方类库ASIHttpRequest
#import "ViewController.h"
#import "ASIFormDataRequest.h"
#import "AppDelegate.h"
#import "ASIDownloadCache.h"
#import "CXMLDocument.h"
@interface ViewController () <UITableViewDataSource,UITableViewDelegate,NSXMLParserDelegate>
{
ASIFormDataRequest *_selectStuInfo;
NSMutableArray *_allStudentsArr; // 所有的学生数组
NSMutableDictionary *_studentDic;
NSString *_currentElementValue; // 当前节点的值
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_allStudentsArr = [NSMutableArray array];
NSString *requestPath = [NSString stringWithFormat:@"%@xml_studentFindJson?page=1&rows=100",REQUEST_URL];
// 缓存策略
[ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];
// 转为国标码
unsigned long encode = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
// 转码utf8
NSString *encoding = [requestPath stringByAddingPercentEscapesUsingEncoding:encode];
NSURL *url = [NSURL URLWithString:encoding];
_selectStuInfo = [ASIHTTPRequest requestWithURL:url];
_selectStuInfo.delegate = self;
// 设置超时时间
_selectStuInfo.timeOutSeconds = 10;
// 超时后重复请求次数
_selectStuInfo.numberOfTimesToRetryOnTimeout = 2;
// 设置缓存策略
[_selectStuInfo setCachePolicy:ASIFallbackToCacheIfLoadFailsCachePolicy|ASIAskServerIfModifiedWhenStaleCachePolicy];
// 设置为永久缓存
[_selectStuInfo setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
// 开始异步请求
[_selectStuInfo startAsynchronous];
}
#pragma mark - ASIHttpRequestDelegate
- (void)requestFinished:(ASIHTTPRequest *)request{
/*--------------------使用NSXMLParser解析--------------------*/
// NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:request.responseData];
// xmlParser.delegate = self;
/* 使用封装
xmlParser.delegate = _stuXMLParserDelegate;
*/
// [xmlParser parse];
// [_tableViewStuInfo reloadData];
/*--------------------使用TouchXML解析--------------------*/
// 使用该方法时不需要 NSXMLParserDelegte 方法
// 将XML内容解析到CXMLDocument对象
CXMLDocument *document = [[CXMLDocument alloc] initWithXMLString:request.responseString options:0 error:nil];
// /:从根节点读取
// //:从匹配的当前节点开始读取,不需要考虑它的位置
NSArray *nodes = [document nodesForXPath:@"//student" error:nil];
for (CXMLDocument *xmlElement in nodes) {
// 取出<student></student>节点
NSArray *array = [xmlElement children];
// 定义一个空的学生对象
NSMutableDictionary *muDic = [NSMutableDictionary dictionary];
// 取出<id></id> <name></name>
for (CXMLDocument *childElement in array) {
[muDic setValue:childElement.stringValue forKey:childElement.name];
}
// 将字典添加入数组
[_allStudentsArr addObject:muDic];
}
[_tableViewStuInfo reloadData];
}
- (void)requestFailed:(ASIHTTPRequest *)request{
NSError *error = [request error];
NSLog(@"网络请求出错--%@",error);
}
#pragma mark - NSXMLParserDelegte
// 当开始处理某个元素节点时触发该方法
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
// NSLog(@"开始处理的元素节点为%@",elementName);
if ([elementName isEqualToString:@"Students"]) {
_allStudentsArr = [NSMutableArray array];
}
if ([elementName isEqualToString:@"student"]) {
_studentDic = [NSMutableDictionary dictionary];
}
}
// 当发现元素中的内容时触发该方法
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
// NSLog(@"开始处理的元素结果为%@",string);
_currentElementValue = string;
}
// 当处理完某个元素节点时触发该方法
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
// NSLog(@"结束处理的元素节点为%@",elementName);
if ([elementName isEqualToString:@"Students"]) {
return;
} else if ([elementName isEqualToString:@"student"]) {
[_allStudentsArr addObject:_studentDic];
} else {
[_studentDic setValue:_currentElementValue forKey:elementName];
_currentElementValue = nil;
}
}
#pragma mark - tableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return _allStudentsArr.count;
/* 使用封装
return _stuXMLParserDelegate.allStudentsArr.count;
*/
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *stringId = @"cellId";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:stringId];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:stringId];
}
NSDictionary *dic = [_allStudentsArr objectAtIndex:indexPath.row];
/* 使用封装
NSDictionary *dic = [_stuXMLParserDelegate.allStudentsArr objectAtIndex:indexPath.row];
*/
cell.textLabel.text = [dic objectForKey:@"name"];
cell.detailTextLabel.text = [dic objectForKey:@"id"];
return cell;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
为了代码的可维护性,可以将 NSXMLParser 进行封装
创建StuXMLParserDelegate文件
.h 文件
#import <Foundation/Foundation.h>
@interface StuXMLParserDelegate : NSObject <NSXMLParserDelegate>
@property (nonatomic,strong) NSMutableArray *allStudentsArr;
@end
.m 文件
#import "StuXMLParserDelegate.h"
@interface StuXMLParserDelegate ()
{
//接受发送的内容
NSString*_currentElementValue;
//接收的字典
NSMutableDictionary*_studentDic;
}
@end
@implementation StuXMLParserDelegate
#pragma mark - NSXMLParserDelegte
// 当开始处理某个元素节点时触发该方法
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
// NSLog(@"开始处理的元素节点为%@",elementName);
if ([elementName isEqualToString:@"Students"]) {
_allStudentsArr = [NSMutableArray array];
}
if ([elementName isEqualToString:@"student"]) {
_studentDic = [NSMutableDictionary dictionary];
}
}
// 当发现元素中的内容是触发该方法
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
// NSLog(@"开始处理的元素结果为%@",string);
_currentElementValue = string;
}
// 当处理完某个元素节点时触发该方法
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
// NSLog(@"结束处理的元素节点为%@",elementName);
if ([elementName isEqualToString:@"Students"]) {
return;
} else if ([elementName isEqualToString:@"student"]) {
[_allStudentsArr addObject:_studentDic];
} else {
[_studentDic setValue:_currentElementValue forKey:elementName];
_currentElementValue = nil;
}
}
本文介绍了XML在iOS中的两种解析方式——SAX解析和DOM解析,重点讲解了苹果自带的NSXMLParser(基于SAX)以及第三方库TouchXML的使用方法,包括各自的优缺点和代码实例。并提供了如何在项目中集成和封装NSXMLParser的建议。
181

被折叠的 条评论
为什么被折叠?



