XML解析--NSXMLParser和TouchXML

本文介绍了XML在iOS中的两种解析方式——SAX解析和DOM解析,重点讲解了苹果自带的NSXMLParser(基于SAX)以及第三方库TouchXML的使用方法,包括各自的优缺点和代码实例。并提供了如何在项目中集成和封装NSXMLParser的建议。

XML有两种解析方式:

  1. SAX解析

SAX:SimpleAPIfor XML。基于事件驱动的解析方式,逐行解析数据。(采用协议回调机制)

  1. 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

  1. TouchXml类库下载链接 —– 注意需要改为mrc 即-fno-objc-arc
  2. 导入 CXMLDocument.h
  3. 开始解析

code案例

此处网络请求使用第三方类库ASIHttpRequest

XML数据

#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;


    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值