1. 使用 NSXMLParser解析XML文档
NSXMLParser 是基于 SAX 的解析器,也就是所谓的“事件驱动”解析器,因此使用 NSXMLParser 解析的关键就是实现 SAX 的时间处理器 --该事件处理器负责处理 NSXMLParser 解析 XML 过程中的各种事件。
NSXMLParser 解析的事件处理采用了委托,因此只要为 NSXMLParser 指定一个 delegate 对象,该对象必须实现 NSXMLParserDelegate 协议
使用 NSXMLParser 解析 XML 文档的步骤:
- 创建 NSXMLParser 对象
- 为 NSXMLParser 对象指定 delegate ,该 delegate 需要实现 NSXMLParserDelegate 协议
- 调用 NSXMLParser 对象的 parse 方法开始解析
2. NSXMLParserDelegate
- -parserDidStartDocument:
- 开始处理 XML 文档时激发
- -parserDidEndDocument:
- 结束处理 XML 文档时激发
- -parser:didStartElement:namespaceURI:qualifiedName:attributes:
- 开始处理 XML 元素时激发
- -parser:didEndElement:namespaceURI:qualifiedName:
- 结束处理 XML 元素时激发
- -parser:didStartMappingPrefix:toURI:
- -parser:didEndMappingPrefix:
- -parser:resolveExternalEntityName:systemID:
- 开始处理外部实体时激发
- -parser:parseErrorOccurred:
- 解析出现错误时激发
- -parser:validationErrorOccurred:
- XML 文档验证错误时激发
- -parser:foundCharacters:
- 解析 XML 文档遇到字符串内容时激发
- -parser:foundIgnorableWhitespace:
- 解析 XML 文档遇到空白时激发
- -parser:foundProcessingInstructionWithTarget:data:
- 解析XML文档处理指令时激发
- -parser:foundComment:
- 处理 XML 文档的注释时激发
- -parser:foundCDATA:
- 处理 XML 文档的 CDATA 内容时激发
3. 代码示例:
3.1 XML 文件
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book id="1">
<title>疯狂iOS讲义</title>
<author>李刚 编著</author>
<remark>基于最新版本的iOS 7</remark>
</book>
<book id="2">
<title>疯狂Java讲义</title>
<author>李刚 编著</author>
<remark>本书来自作者3年的Java培训经历,凝结了作者近3000个小时的授课经验</remark>
</book>
<book id="3">
<title>轻量级Java EE企业应用实战</title>
<author>李刚 编著</author>
<remark>本书主要介绍以Spring+Hibernate+Struts2为基础的Java EE应用</remark>
</book>
<book id="4">
<title>疯狂Android讲义</title>
<author>李刚 编著</author>
<remark>本书第一版长期雄踞各网店、书店Android图书销量排行榜前列</remark>
</book>
</books>
3.2 model 类
#import <Foundation/Foundation.h>
@interface FKBook : NSObject
@property (nonatomic , assign) NSInteger bookID;
@property (nonatomic , copy) NSString *title;
@property (nonatomic , copy) NSString *author;
@property (nonatomic , copy) NSString *remark;
@end
3.3 自定义 delegate
.h文件:
#import <Foundation/Foundation.h>
@interface FKXMLPraserDelegate : NSObject <NSXMLParserDelegate>
// 定义一个NSMutableArray集合来保存解析XML文档得到的数据
@property (nonatomic, strong) NSMutableArray *books;
@end
.m文件:
#import "FKXMLPraserDelegate.h"
#import "FKBook.h"
@implementation FKXMLPraserDelegate
// 定义一个FKBook对象,用于保存正在解析的<book>元素中的数据
FKBook* book;
NSString* currentElementValue;
// 当开始处理某个元素时触发该方法
-(void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
NSLog(@"开始处理元素 %@" , elementName);
if([elementName isEqualToString:@"books"])
{
// 如果正在处理根元素,在此处初始化存储解析结果的NSMutableArray集合
self.books = [[NSMutableArray alloc] init];
}
// 如果正在处理<book.../>元素
else if([elementName isEqualToString:@"book"])
{
// 初始化FKBook对象
book = [[FKBook alloc] init];
// 从attributeDict中读取<book.../>元素的属性id的值
book.bookID = [[attributeDict objectForKey:@"id"] integerValue];
}
}
// 当开始处理字符串内容时触发该方法
-(void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
NSLog(@"处理字符串内容:%@",string);
// 如果当前的字符串值不为nil,保存当前正在处理的元素的值
if(string)
{
currentElementValue = string;
}
}
// 当处理某个元素结束时触发该方法
-(void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
// 如果处理根元素结束,表明XML文档处理完成。
if([elementName isEqualToString:@"books"])
{
return;
}
// 如果处理<book.../>元素结束,则将封装的FKBook对象添加到NSMutableArray集合中
else if([elementName isEqualToString:@"book"])
{
[self.books addObject: book];
book = nil;
}
else
{
// 如果既不是处理<books.../>元素,也不是处理<book.../>元素的时候,
// 则使用KVC方式为当前FKBook对象的属性赋值
[book setValue:currentElementValue forKey:elementName];
currentElementValue = nil;
}
}
@end
3.4 调用
// 获取要解析的XML文档的所在的URL(使用URL即可解析本地XML文档,也可解析网络XML文档)
NSURL* fileUrl = [[NSBundle mainBundle]
URLForResource:@"books" withExtension:@"xml"];
// 获取NSXMLParser实例对象
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:fileUrl];
// 创建NSXMLParser解析的委托对象。
parserDeletage = [[FKXMLPraserDelegate alloc] init];
// 为NSXMLParser指定委托对象,该委托对象就负责处理解析事件
parser.delegate = parserDeletage;
// 开始解析, 解析结果会保存在委托对象的books属性中
[parser parse];