前言
在iOS开发中,数据解析通常有两种方式,一种是JSON解析,一种是XML解析。今天着重讲解一下XML文件解析的三种方式。
- 解析下面这样一个XML文件
- 点击下载:XML文件
准备工作
- 首先创建一个Student模型
- student.h
#import <Foundation/Foundation.h>
@interface Student : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *gender;
@property (nonatomic, copy) NSString *age;
@property (nonatomic, copy) NSString *nickname;
@end
- student.m
#import "Student.h"
@implementation Student
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
}
@end
- 重写setValue:forUndefinedKey防止程序crash
- 在storyboard里拖两个button,名字分别为SAX和DOM
- 关联点击事件,取名为saxAction和domAction
- 导入头文件,签订协议,设置属性
#import "ViewController.h"
#import "Student.h"
#import "GDataXMLNode.h"
#import "XMLReader.h"
@interface ViewController ()
<
NSXMLParserDelegate
>
@property (nonatomic, retain) NSMutableArray *studentArray;
// 用来记录当前xml解析的节点名称
@property (nonatomic, copy) NSString *currentElementName;
@end
方式一:SAX解析
- SAX解析的特点是逐行进行解释
#pragma mark - SAX解析
// SAX 逐行解析
- (IBAction)saxAction:(id)sender {
NSString *xmlFilePath = [[NSBundle mainBundle] pathForResource:@"Demo.xml" ofType:nil];
NSData *xmlData = [NSData dataWithContentsOfFile:xmlFilePath];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:xmlData];
xmlParser.delegate = self;
// 开始解析
[xmlParser parse];
}
# pragma mark - 协议方法
// 开始
- (void)parserDidStartDocument:(NSXMLParser *)parser {
NSLog(@"开始");
self.studentArray = [NSMutableArray array];
}
// 获取节点头
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict {
NSLog(@"start element : %@", elementName);
self.currentElementName = elementName;
if ([elementName isEqualToString:@"student"]) {
Student *stu = [[Student alloc] init];
[_studentArray addObject:stu];
}
}
// 获取节点的值 (这个方法在获取到节点头和节点尾后,会分别调用一次)
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
NSLog(@"value : %@", string);
if (_currentElementName != nil) {
Student *stu = [_studentArray lastObject];
[stu setValue:string forKey:_currentElementName];
}
}
// 获取节点尾
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
_currentElementName = nil;
NSLog(@"end element :%@", elementName);
}
// 结束
- (void)parserDidEndDocument:(NSXMLParser *)parser {
NSLog(@"结束");
NSLog(@"%@",_studentArray);
}
方式二:DOM解析
- DOM解析的特点是通过节点解析
- 使用第三方类库
- 点击下载:GDataXMLNode
- 当前工程使用的是ARC
- 导入头文件后的准备工作
- 第一步
- 第二步
- 第三步
- 第四步
- 复制下面这句话进去
/usr/include/libxml2
- 第五步
- 复制下面这句话进去
-fno-objc-arc
- 代码
# pragma mark - DOM按节点解析
- (IBAction)domAction:(id)sender {
self.studentArray = [NSMutableArray array];
NSString *xmlFilePath = [[NSBundle mainBundle] pathForResource:@"Demo.xml" ofType:nil];
NSData *xmlData = [NSData dataWithContentsOfFile:xmlFilePath];
NSError *error = nil;
GDataXMLDocument *xmlDocument = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
if (error) {
NSLog(@"error : %@", error);
return;
}
// 取根节点
GDataXMLElement *rootElement = [xmlDocument rootElement];
// 获取根节点下的所有子节点
NSArray *elementArray = rootElement.children;
for (GDataXMLElement *studentElement in elementArray) {
Student *stu = [[Student alloc] init];
[_studentArray addObject:stu];
for (GDataXMLElement *attributeElement in studentElement.children) {
[stu setValue:attributeElement.stringValue forKey:attributeElement.name];
}
}
NSLog(@"array : %@", _studentArray);
}
@end
第三种方式:XMLReader解析
- XMLReader通过向前读取文档并识别读取到的元素
- 为我们提供了一种消耗资源最少的方式来解析XML数据
- 点击下载:XMLReader
- 下载完成后导入整个文件到项目里
- (void)viewDidLoad {
[super viewDidLoad];
NSString *xmlFileString = [[NSBundle mainBundle] pathForResource:@"Demo" ofType:@"xml"];
NSData *xmlData = [NSData dataWithContentsOfFile:xmlFileString];
NSError *error = nil;
if (error) {
NSLog(@"error : %@", error);
}
NSDictionary *result = [XMLReader dictionaryForXMLData:xmlData error:&error];
NSLog(@"result : %@", result);
}
- 通过XMLReader最后拿到的是一个字典
总结
- XML优点
- 格式统一,符合标准
- 容易与其他系统进行远程交互,数据共享比较方便
- XML的缺点
- XML文件庞大,文件格式复杂,传输占带宽
- 服务器端和客户端都需要花费大量代码来解析XML,导致服务器端和客户端代码变得异常复杂且不易维护
- 客户端不同浏览器之间解析XML的方式不一致,需要重复编写很多代码
- 服务器端和客户端解析XML花费较多的资源和时间