XML解析方式:
1,SAX(Simple API for XML)
只能读,不能修改。读一个节点就解析一个节点,适合解析大型XML,解析速度快。
2,DOM(Document Object Model)
能读能修改。加载整个XML,形成DOM树,内存占用高,适合解析小型文档,解析速度慢。
NSXMLParser是SAX解析方式。
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:
下面这个Demo演示了使用NSXMLParser解析XML文件,要解析的XML文件内容如下:
JavaScript开发
毕向东
28.00
JavaWeb开发
方立勋
36.00
iOS开发
李明杰
42.00
源码下载地址:http://download.youkuaiyun.com/detail/liu537192/8573023
效果图:
核心代码:
//
// JLViewController.m
// 03-xml解析
//
// Created by Mac on 15-4-7.
// Copyright (c) 2015年 vxinyou. All rights reserved.
//
#import "JLViewController.h"
#import "JLBook.h"
@interface JLViewController ()
@property (nonatomic, strong)NSMutableArray *books;
@property (nonatomic, strong)JLBook *book;
@property (nonatomic, strong)NSMutableString *elementStr;
@end
@implementation JLViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
/**
* 加载xml数据
*/
- (IBAction)loadXmlData{
// 显示下拉刷新
[self.refreshControl beginRefreshing];
// 创建一个队列
dispatch_queue_t queue = dispatch_queue_create("demo", DISPATCH_QUEUE_CONCURRENT);
// 异步执行队列中的任务
dispatch_async(queue, ^{
// 这里是子线程
// NSLog(@"%@", [NSThread currentThread]);
// 模拟网络请求,延迟2秒
[NSThread sleepForTimeInterval:2.0f];
NSString *xmlPath = [[NSBundle mainBundle] pathForResource:@"books.xml" ofType:nil];
NSData *xmlData = [NSData dataWithContentsOfFile:xmlPath];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:xmlData];
// 设置代理
xmlParser.delegate = self;
// 开始解析。因为这里是在子线程中执行的,会使NSXMLParser的代理方法都在子线程中执行。
[xmlParser parse];
});
}
#pragma mark -隐藏状态栏
- (BOOL)prefersStatusBarHidden{
return YES;
}
#pragma mark -UITableView的代理方法
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.books.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *ID = @"book";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
JLBook *book = self.books[indexPath.row];
cell.textLabel.text = book.name;
cell.detailTextLabel.text = [NSString stringWithFormat:@"作者:%@--价格:%.2f", book.author, book.price];
return cell;
}
#pragma mark -延迟加载方法
- (NSMutableArray *)books{
if (_books == nil) {
_books = [NSMutableArray array];
}
return _books;
}
- (NSMutableString *)elementStr{
if (_elementStr == nil) {
_elementStr = [NSMutableString string];
}
return _elementStr;
}
#pragma mark -NSXMLParser的代理方法
/**
* 开始解析
*/
- (void)parserDidStartDocument:(NSXMLParser *)parser{
NSLog(@"开始解析文档");
// 这里是子线程
// NSLog(@"%@", [NSThread currentThread]);
[self.books removeAllObjects];
[self.elementStr setString:@""];
}
/**
* 解析到节点的开始部分:
、
、
、
*/
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
NSLog(@"%@", elementName);
// 这里是子线程
// NSLog(@"%@", [NSThread currentThread]);
if ([elementName isEqualToString:@"book"]) {
self.book = [[JLBook alloc] init];
self.book.ID = attributeDict[@"id"];
}
// 清除上次的内容
[self.elementStr setString:@""];
}
/**
* 查找内容
*/
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
NSLog(@"%@", string);
// 这里是子线程
// NSLog(@"%@", [NSThread currentThread]);
[self.elementStr appendString:string];
}
/**
* 解析到节点的结束部分:
、、、
*/
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
NSLog(@"%@", elementName);
// 这里是子线程
// NSLog(@"%@", [NSThread currentThread]);
if ([elementName isEqualToString:@"name"]) {
self.book.name = self.elementStr;
}else if ([elementName isEqualToString:@"author"]){
self.book.author = self.elementStr;
}else if ([elementName isEqualToString:@"price"]){
self.book.price = [self.elementStr intValue];
}else if ([elementName isEqualToString:@"book"]){
[self.books addObject:self.book];
}
}
/**
* 解析结束
*/
- (void)parserDidEndDocument:(NSXMLParser *)parser{
NSLog(@"解析文档结束");
// 这里是子线程
// NSLog(@"%@", [NSThread currentThread]);
// 在主线程中更新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// 这里是主线程
// NSLog(@"%@", [NSThread currentThread]);
// 重新加载数据
[self.tableView reloadData];
// 关闭下拉刷新
[self.refreshControl endRefreshing];
}];
}
/**
* 解析出错
*/
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{
NSLog(@"%@", parseError.localizedDescription);
}
@end
//
// JLBook.h
// 03-xml解析
//
// Created by Mac on 15-4-7.
// Copyright (c) 2015年 vxinyou. All rights reserved.
//
#import
@interface JLBook : NSObject
@property (nonatomic, strong)NSNumber *ID;
@property (nonatomic, copy)NSString *name;
@property (nonatomic, copy)NSString *author;
@property (nonatomic, assign)CGFloat price;
@end
//
// JLBook.m
// 03-xml解析
//
// Created by Mac on 15-4-7.
// Copyright (c) 2015年 vxinyou. All rights reserved.
//
#import "JLBook.h"
@implementation JLBook
@end
下面2张图说明了如何使用下拉刷新:
选中整个UITableViewController,设置其Refreshing属性为Enabled:
给Refresh Control关联一个方法: