您的位置:首页 > 理论基础 > 数据结构算法

UI_16 XML、JSON数据结构解析

2015-09-05 20:49 148 查看
从事先规定好的格式中提取数据,即为解析。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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: