本文利用苹果自带的、基于SAX的解析器:NSXMLParser和基于libxml2的DOM方式的GDataXML解析本地XML文件。前者也就是所谓的“事件驱动”的解析器。
新建项目,向项目中添加一个.xml文件,如下xml文件:
<books>
<book id = "1">
<title>西游记</title>
<author>吴承恩</author>
<remark>孙悟空</remark>
</book>
<book id = "2">
<title>红楼梦</title>
<author>曹雪芹</author>
<remark>林黛玉</remark>
</book>
<book id = "3">
<title>水浒传</title>
<author>施耐庵</author>
<remark>林冲</remark>
</book>
<book id = "4">
<title>三国演义</title>
<author>罗贯中</author>
<remark>曹操</remark>
</book>
</books>
在控制器.m文件中提前声明两个变量:
HXBook *book;// 模型
NSString*currentString;// 当前解析到的元素之间的字符内容
在控制器view加载完毕后,加载xml文件,并利用xml文件创建NSXMLParser对象,设置代理,再调用NSXMLParser对象的parse方法开始解析。如下:
- (void)viewDidLoad {
[super viewDidLoad];
// NSURL *pathURL = [[NSBundle mainBundle] URLForResource:@"text" withExtension:@"xml"];
NSString *path = [[NSBundle mainBundle] pathForResource:@"text.xml" ofType:nil];
NSData *data = [NSData dataWithContentsOfFile:path];
// 根据xml文件创建NSXMLParser对象
// NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:pathURL];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
// 设置代理
parser.delegate = self;
// 开始解析(SAX解析)
[parser parse];
}
#pragma mark NSXMLParserDelegate
/**
* 当扫描到文档的开始时调用(开始解析)
*/
- (void)parserDidStartDocument:(NSXMLParser *)parser {
NSLog(@"开始解析");
}
/**
* 当扫描到文档的结尾时调用(结束解析)
*/
- (void)parserDidEndDocument:(NSXMLParser *)parser {
NSLog(@"结束解析");
for (HXBook *b in self.books) {
NSLog(@"书:%@", b.remark);
}
}
/**
* 当扫描到一个元素的开始时候调用(attributeDict存放着元unsude属性)
*/
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict {
NSLog(@"开始处理元素:%@", elementName);
if ([elementName isEqualToString:@"book"]) {
// 创建模型
book = [[HXBook alloc] init];
book.ID = [[attributeDict objectForKey:@"id"] integerValue];
}
}
/**
* 解析到元素间的字符内容时调用
*/
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
NSLog(@"处理的字符内容:%@", string);
// 如果当前字符内容不为nil,则保存当前字符内容
if (string) {
currentString = string;
}
}
/**
* 当扫描到一个元素的结尾时候调用
*/
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
NSLog(@"结束处理元素:%@", elementName);
if ([elementName isEqualToString:@"book"]) {
// 添加模型到模型数组中
[self.books addObject:book];
// 重置book
book = nil;
}else {// 解析的不是<books.../>也不是<book.../>元素
// 利用KVC方式为当前HXBook对象的属性赋值
[book setValue:currentString forKey:elementName];
// 重置currentString
currentString = nil;
}
}
运行后,parser开始解析,打印如下:
下面介绍是用基于DOM方式的GDataXML解析XML文件。先根据这篇文章配置好环境。将GDataXMLNode.h和GDataXMLNode.m文件拖进项目中。
代码如下:
- (void)testGDataXML {
// 获取XML文件路径
NSString *path = [[NSBundle mainBundle] pathForResource:@"text.xml" ofType:nil];
NSString *xmlString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
// 根据XML文件路径加载XML文件
GDataXMLDocument *xmlDocu = [[GDataXMLDocument alloc] initWithXMLString:xmlString options:0 error:nil];
// 根据XML文件,获取XML文件中的根元素
GDataXMLElement *xmlEle = [xmlDocu rootElement];
// 在根据主元素,获取其下面的所有直接子元素
NSArray *array = [xmlEle children];
NSLog(@"array.count = %lu", (unsigned long)array.count);
// 遍历所有子元素
for (int i = 0; i < array.count; i ++) {
// 获取对应索引的子元素
GDataXMLElement *element = [array objectAtIndex:i];
// 根据元素判断
if ([[element name] isEqualToString:@"book"]) {
// 创建模型
book = [[HXBook alloc] init];
//取出元素中属性值
NSString *IDString = [[element attributeForName:@"id"] stringValue];
book.ID = [IDString integerValue];
// 获取"book"下的所有直接子元素
NSArray *childs = [element children];
for (int j = 0; j < childs.count; j ++) {
GDataXMLElement *chilE = [childs objectAtIndex:j];
if ([[chilE name] isEqualToString:@"title"]) {
// 书名
NSString *title = [chilE stringValue];
book.title = title;
}else if ([[chilE name] isEqualToString:@"author"]) {
// 作者
NSString *author = [chilE stringValue];
book.author = author;
}else {
// 人物
NSString *remark = [chilE stringValue];
book.remark = remark;
}
}
[self.books addObject:book];
book = nil;
}
}
// 转换模型完毕后
for (HXBook *b in self.books) {
NSLog(@"书:%@", b.remark);
}
}
运行结果:
GDataXML是利用根元素的直接子元素来获取内容的。根元素和子元素是相对的。
两种解析XML的方法就介绍到这里。