从事先规定好的格式中提取数据,即为解析。iOS开发常见的解析有:XML解析、JSON解析
一、XML解析
XML:Extensible Markup language(可扩展标记语⾔),主流数 据格式之⼀,可以⽤来存储和传输数据。
XML的解析有很多选择,iOS SDK提供了NSXMLParser和libxml2两个类库,另外还有很多第三方类库可选,例如TBXML、TouchXML、KissXML、TinyXML和GDataXML。如何选择?
如果是读取很小的XML文档,性能基本上没有什么差别,不过从调用的方便性来说,建议使用TouchXML、KissXML或GDataXML
如果是需要读取和修改XML文档,建议使用KissXML或GDataXML
如果需要读取非常大的XML文档,则建议使用libxml2、NSXMLParser或TBXML
更多XML解析选择性问题请看 iOS平台XML解析类库对比和安装说明
1、XML数据结构
Student文件内容:
<?xml version="1.0" encoding="UTF-8"?>
<students>
<student>
<name>张三</name>
<number>1</number>
<address>如家401</address>
</student>
<student>
<name>傻逼</name>
<number>3</number>
<address>如家403</address>
</student>
<student>
<name>二货</name>
<number>2</number>
<address>如家402</address>
</student>
</students>
2、SAX解析
SAX:Simple API for XML。基于事件驱动的解析⽅式,逐⾏解析 数据。(采⽤协议回调机制)
2.1NSXMLParser
NSXMLParser是iOS⾃带的XML解析类。采⽤SAX⽅式解析数据。
解析过程由NSXMLParserDelegate协议⽅法回调
解析过程:开始标签->取值->结束标签->取值
2.2示例
使用xib添加UIButton并关联didClickSAX:事件
在延展中声明实例变量_currentElementName接收开始标签的名字
声明属性studentsArray用来存储YFStudent模型
遵守 NSXMLParserDelegate协议并实现必要的方法
@interface ViewController ()<NSXMLParserDelegate>
{
NSString *_currentElementName; //用来临时接收开始标签的名字
}
@property(nonatomic, retain) NSMutableArray *studentsArray;
- (IBAction)didClickSAX:(UIButton *)sender;
@end
实现部分的代码如下:
#pragma mark -- 使用SAX方式解析XML,采用的是协议回调机制,逐行解析数据,使用NSXMLParser --
- (IBAction)didClickSAX:(UIButton *)sender {
//1.获取文件
NSString *path = [[NSBundle mainBundle] pathForResource:@"Students" ofType:nil];
//2.根据文件路径获取文件中的数据,并将其转换为NSData类型的数据
NSData *data = [NSData dataWithContentsOfFile:path];
//3.解析数据
//3.1创建解析数据的工具对象
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
//3.2设置代理
parser.delegate = self;
//3.3开始解析
[parser parse];
}
#pragma mark -- NSXMLParserDelegate --
//1.开始、结束解析文档
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
self.studentsArray = [NSMutableArray array];
NSLog(@"%s", __FUNCTION__);
}
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
NSLog(@"%s", __FUNCTION__);
}
//2.解析元素
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
_currentElementName = elementName;
NSLog(@"%s, %@", __FUNCTION__, elementName);
if ([elementName isEqualToString:@"student"]) {
YFStudent *student = [[YFStudent alloc] init];
[_studentsArray addObject:student];
[student release];
}
} //“开始标签”
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
//执行顺序:开始标签-取值-结束标签-取值;若不置空,结束标签后的换行符会覆盖之前的值
_currentElementName = nil;
NSLog(@"%s", __FUNCTION__);
NSLog(@"%s, %@", __FUNCTION__, elementName);
} //“结束标签”
//3.取标签后的值
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
YFStudent *student = [_studentsArray lastObject];
[student setValue:string forKey:_currentElementName];
NSLog(@"%s, %@", __FUNCTION__, string);
}
3、DOM解析
DOM:Document Object Model(⽂档对象模型)。解析时需要 将XML⽂件整体读⼊,并且将XML结构化成树状,使⽤时再通过树 状结构读取相关数据
3.1GDataXMLNode
GDataXMLNode采⽤DOM⽅式解析数据,是Google提供的开源XML解析类,对libxml2.dylib进⾏了Objective-C的封装。iOS中包含⼀个C语⾔的动态链接库libxml2.dylib,解析速度⽐NSXMLParser快但需要:
配置环境变量
由于GDataXML是非ARC的,因此得设置编译参数
3.2示例
在延展中声明属性studentsArray用来存储YFStudent模型
@property(nonatomic, retain) NSMutableArray *studentsArray;
在xib中添加按钮并关联事件
- (IBAction)didClickDOM:(UIButton *)sender;
实现解析
#pragma mark -- 使用DOM方式解析XML格式(会将整个xml文件读入内存,用数组以树状结构进行存放) --
- (IBAction)didClickDOM:(UIButton *)sender {
//1.获取xml文件路径
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Students" ofType:nil];
//2.转换成NSData
NSData *data = [NSData dataWithContentsOfFile:filePath];
//3.解析
//3.1创建GDataXMLNode对象
NSError *error = nil;
GDataXMLDocument *xmlDocument = [[GDataXMLDocument alloc] initWithData:data options:0 error:&error]; //将整个data数据读入内存,存在GDataXMLDocument对象里(xmlDocument)
NSMutableArray *stuArray = [NSMutableArray array];
//3.2获得根节点
GDataXMLElement *rootElement = xmlDocument.rootElement;
//3.3遍历节点
for (GDataXMLElement *childElement in rootElement.children) {
YFStudent *student = [[YFStudent alloc] init];
for (GDataXMLElement *element in childElement.children) {
//叶子节点值、标签名
[student setValue:element.stringValue forKey:element.name];
}
[stuArray addObject:student];
}
#warning mark -- 获取所有name节点中的值
NSArray *nameArr = [xmlDocument nodesForXPath:@"//name" error:nil];
for (GDataXMLElement *element in nameArr) {
NSLog(@"%@", element.stringValue);
}
}
二、JSON解析
Javascript Object Notation,轻量级的数据交换格式,采⽤完全 独⽴于语⾔的⽂本格式,被称为理想的数据交换语⾔。
JSON解析⼯具:JSONKit、NSJSONSerialization、TouchJSON和SBJSON 等,其中NSJSONSerialization是系统提供的解析类,其解析效率是最⾼的
1、JSON数据结构
JSON⽂档有两种结构:对象、数组
对象:以“{”开始,以“}”结束,是“名称/值”对⼉的集合。名称和值中间⽤“:”隔开。多个“名称/值”对之间⽤“,”隔开。类似OC中的字典。
数组:以“[”开始,以“]”结束,中间是数据。数据以“,”分隔。
JSON中的数据类型:字符串、数值、BOOL、对象、数组。
Teacher文件内容:
[{"name":"张三","number":"1","sex":"男"},{"name":"李四","number":"2","sex":"男"},{"name":"王五","number":"3","sex":"女"}]
结构太乱看不清?下面的工具会帮到你
http://www.bejson.com/jsonviewernew/
2、解析示例
#pragma mark -- JSON解析(NSJSONSerialization和JSONKit方式) --
- (IBAction)didClickJSON:(UIButton *)sender {
//第一种:NSJSONSerialization
//1.path
NSString *path = [[NSBundle mainBundle] pathForResource:@"Teacher" ofType:nil];
//2.NSData
NSData *data = [NSData dataWithContentsOfFile:path];
//3.解析
NSMutableArray *array = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; //关于options参数请看最后
self.teachersArray = [NSMutableArray array];
for (NSDictionary *dict in array) {
YFTeacher *teacher = [[YFTeacher alloc] init];
[teacher setValuesForKeysWithDictionary:dict];
[_teachersArray addObject:teacher];
}
for (YFTeacher *teacher in _teachersArray) {
NSLog(@"%@", [teacher description]);
}
//第二种:JSONKit
NSMutableArray *array1 = [data objectFromJSONData]; //array1内容与上边array相同,之后过程略
NSDictionary *dict = @{@"key":@[@"A",@"B",@"C"]};
//将字典转化为NSData类型的数据
NSData *data1 = [dict JSONData]; //<7b226b65 79223a5b 2241222c 2242222c 2243225d 7d>
//将字典转化为NSString类型的数据
NSString *dictStr = [dict JSONString]; //{"key":["A","B","C"]}
}
关于NSJSONReadingOptions:
NSJSONReadingMutableContainers:返回可变容器,NSMutableDictionary或NSMutableArray。
NSJSONReadingMutableLeaves:返回的JSON对象中字符串的值为NSMutableString,目前在iOS 7上测试不好用,应该是个bug,参见:
http://stackoverflow.com/questions/19345864/nsjsonreadingmutableleaves-option-is-not-working
NSJSONReadingAllowFragments:允许JSON字符串最外层既不是NSArray也不是NSDictionary,但必须是有效的JSON Fragment。例如使用这个选项可以解析 @“123” 这样的字符串。参见:
http://stackoverflow.com/questions/16961025/nsjsonserialization-nsjsonreadingallowfragments-reading