网络解析
数据解析:从某种格式的数据中提取自己所需要的数据
主流的数据交换格式有两种:XML和JSON.
----XML-----
1:可扩展标记语言(Extensible Markup Language)
2:跟JSON解析一样,常用于交互的数据格式
3:一般XML文档(XML Document)
4:举例:
<student>[标签,表示开始]
<name>你</name>
<hobby>女</hobby>
</student>[表示结束]
5:XML文档的语法
5.1:文档声明:在XML文档最前面,必须写一个文档声明.
- ①最简单的声明:<?xml version="1.0"?>
- ②用encoding属性,来说明文档字符编码:<?xml version="1.0" encoding= "UTF-8"?>
5.2:元素(Element):一个元素,会包含一个开始标签和一个结束标签
- ①有元素内容:<name>你</name>
- ②无元素内容:<name></name>
而且一个元素可以嵌套若干子元素,但不能出现交叉嵌套
注意:- 1:规范的XML文档最多只有一个根元素,其他的都是根元素的子元素.
- 2:在XML文档中空格和换行都会被当做具体内容去处理,例如:①和②是不一样的
①<name>你</name>
② <name>
你
</name>
5.3:属性(Atribute):一个元素可以拥有多个属性,例如
<video name="小黄人" hobby="banana"/>
[video元素拥有name,hobby两个属性]
注意:属性的值必须用" "
或者' '
括住
属性表示的信息也可用子元素表示,例如:
<video>
<name>小黄人</name>
<hobby>banana</hobby>
</video>
6:对XML文档的解析:
提取name
元素里面的内容:<name>小黄人</name>
或者是提取video
元素中name
和hobby
的值<video name="小黄人" hobby="banana"/>
------SAX(Simple API for XML)解析----
<students>
<student>
<name>你</name>
<hobby>女</hobby>
</student>
</students>
1:解析方式,逐行进行解析
1.1:打开XML文档
1.2:开始节点(开始标签)
1.2.1<students>
1.2.2<student>
1.2.3<name>
1.3:发现元素里面的内容
1.3.1提取到"你"
1.4:结束节点(结束标签)
1.4.1</name>
1.5:循环开始,直到遇到</students>解析才彻底结束
iOS中XML解析方式有很多
- 2.1:苹果原生:NSXMLParser--SAX方式解析,使用简单
- 2.2:第三方框架:
- ①libxml2:纯c语言,默认被包含进了iOS SDK,同时支持DOM和SAX解析
- ②GDataXML:DOM的解析方式,是由谷歌开发的,底层基于libxml2
下边就上边的students例子作简单说明下SAX解析
-(void)Btn{
//获取文档路径
NSString *path = [[NSBundle mainBundle]pathForResource:@"XML" ofType:@"txt"];
//通过路径,创建一个data对象
NSData *data = [NSData dataWithContentsOfFile:path];
//创建SAX解析使用的对象
NSXMLParser *xmlParser = [[NSXMLParser alloc]initWithData:data];
//遵循代理
xmlParser.delegate = self;
//开始解析
[xmlParser parse];
}
#pragma mark-----NSXMLParserDelegate方法-----
//1:开始解析XML文档
- (void)parserDidStartDocument:(NSXMLParser *)parser{
//准备数据(自动根据元素个数开辟空间,最好先给0)
self.dataArray = [NSMutableArray arrayWithCapacity:0];
}
//2:开始解析标签(节点)
/*
parser:(NSXMLParser *)parser 类
didStartElement:(NSString *)elementName 标签名
namespaceURI:(NSString *)namespaceURI 节点里的命名空间
*/
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict{
//获取到当前正在解析的标签,给标签属性赋值
_currentElement = elementName;
//如果当前解析到的标签值为"student'
if ([elementName isEqualToString:@"student"]) {
//创建并初始化model,如果标签是"student"那么创建model类,并添加到数据源数组中(如果不是,model的预建立)
Student *stu = [Student new];
[self.dataArray addObject:stu];
}
}
//3:读取标签的值:这个方法,得到节点里面的存的信息数据
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
//将值存入model类对应的属性中,这个方法循环执行,我们需要取得值是最后一个[包<student></student>,是按照顺序扔进数组的,挨个进行取值,所以只取最后一个,说明全部取完]
Student *stu = self.dataArray.lastObject;//找到对应的地址
//根据当前已经解析出来的标签取到跟stu中属性对应的值,赋值给stu中的属性
[stu setValue:string forKey:_currentElement]; //通过地址给属性赋值
}
//4:结束标签解析
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
//没有标签,结束解析
_currentElement = nil;
}
//5:结束解析文档
- (void)parserDidEndDocument:(NSXMLParser *)parser{
for (Student *stu in self.dataArray) {
NSLog(@"%@",stu);
}
}
//6:错误信息
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{
NSLog(@"%@",parseError);
}
------DOM(Document Object Model)解析----
1.Document object Model(文档对象模型),将整个XML文档读入,构建驻留内存的树结构(节点数),通过遍历树结构的任意节点,读取他的属性和值
2:步骤
- 2.1:获取GDataXMLNode.h文件,将GDataXMLNode.m添加到所需工程
- 2.2:添加类库libxml2.tbd到工程中
- 2.3:在工程中的"Build settings"页面中找到"Header Search path"项,添加"/usr/include/libxml2"
同样以前面的例子为例,加以代码说明
//获取文件路径
NSString *path =[[NSBundle mainBundle]pathForResource:@"XML" ofType:@"txt"];
//以data类型进行解析
NSData *data = [NSData dataWithContentsOfFile:path];
//创建GDataXMLDocument对象,此时XML文档内的所有节点,以树的形式存在于GDataXMLDocument对象中
GDataXMLDocument *xmlDocument = [[GDataXMLDocument alloc]initWithData:data options:0 error:nil];
//创建节点对象,获取XML文档的根节点,根节点里包含了XML文档中所有的内容
GDataXMLElement *rootElement = [xmlDocument rootElement];
//创建解析出来的学生数组
self.dataArray = [NSMutableArray array];
//遍历根节点<students>的所有子节点
for (GDataXMLElement *sbuelement in rootElement.children) {
Student *stu = [Student new];
//在遍历子节点下的子节点,取出子标签的内容,赋值给stu
for (GDataXMLElement *contactelement in sbuelement.children) {
//使用KVC对stu整个赋值
[stu setValue:contactelement.stringValue forKeyPath:contactelement.name];
}
//将赋值后的model类放入数据源数组
[self.dataArray addObject:stu];
}
//打印结果
for (Student *stu in self.dataArray) {
NSLog(@"%@",stu);
}
}
----JSON解析----
1:JSON(JavaScript Object Notation),轻量级的数据交换格式,是基于JS的一个子集,是完全采用独立语言的文本格式,容易阅读和编写,非常适合于服务器和客户端的交互
2:注意:标准的JSON格式:Key必须用双引号.
3:在iOS中常见的JSON解析方式
- 3.1:原生(自带): NSJSONSerialization(性能最好)
- 3.2:第三方:JSONKit,SBJSON,TouchJSON(依次从左到右,越来越差)
4:JSON--- OC:两者对应的数据类型
- ①JSON中''{}'',在OC中表示NSDictionary
- ②JSON中"[]",在OC中表示NSArray
- ③JSON中双引号,在OC中表示NSString
5:数组下的每一个字典需要逗号分隔
以下的同样是以Student类为例,先注册Student类
先看下系统源生态的解析方法
#pragma mark-----JSON-FOUNDATION(系统自带)-----
-(void)Btn{
//获取文件路径
NSString *path = [[NSBundle mainBundle]pathForResource:@"JSON" ofType:@"txt"];
//创建数据对象(data类型)
NSData *data = [NSData dataWithContentsOfFile:path];
/*
JSONObjectWithData:<#(nonnull NSData *)#> options:<#(NSJSONReadingOptions)#> error:<#(NSError * _Nullable __autoreleasing * _Nullable)#>
参数1:放入数据对象源
参数2:
NSJSONReadingMutableContainers = (1UL << 0),表示解析完成后返回值类型为NSMutableArray
NSJSONReadingMutableLeaves = (1UL << 1),表示解析完成返回值类型是NSMutableString
NSJSONReadingAllowFragments = (1UL << 2),允许JSON串最外层即不是数组也不是字典,但必须是JSON有效片断
参数3:错误信息
*/
//解析JSON数据,使用系统方法
NSArray *array = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingAllowFragments error:nil];
//初始化数据源
self.dataArray = [NSMutableArray array];
//遍历数组,放入字典
for (NSDictionary *dic in array) {
//初始化model类
Student *stu = [Student new];
//使用KVC进行赋值
[stu setValuesForKeysWithDictionary:dic];
//将赋值后的model类放入数据源数组中
[self.dataArray addObject:stu];
}
for (Student *stu in self.dataArray) {
NSLog(@"%@",stu);
}
}
JSON下第三方的解析方式里,就拿性能最好的JSONKit举例.
#pragma mark-----JSON-KIT(第三方)-----
-(void)Btn{
NSString *path = [[NSBundle mainBundle]pathForResource:@"JSON" ofType:@"txt"];
//创建data对象
NSData *data = [NSData dataWithContentsOfFile:path];
//获取数据,使用JSONKit中的
NSArray *array = [data objectFromJSONData];
NSLog(@"%@",array);
//初始化数据源数组
self.dataArray = [NSMutableArray array];
for (NSDictionary *dic in array) {
//初始化model
Student *stu = [Student new];
//kvc赋值
[stu setValuesForKeysWithDictionary:dic];
[self.dataArray addObject:stu];
}
for (Student *stu in self.dataArray) {
NSLog(@"%@",stu);
}
}
上面说了那么多,最后来总结下XML和JSON的优缺点吧.
首先XML
优点:
- 1:格式统一,符合标准
- 2:容易与其他系统进行远程交互,数据共享比较方便.
缺点:
- 1:XML文件格式文件庞大,格式复杂,传输占用宽带.
- 2:服务器端和客户端都需要花费大量代码来解释XML,不论服务器端还是客户端都使代码变得异常复杂和不容易维护.
- 3:客户端不同浏览器之间解析XML的方式不一致,需要重复编写很多代码
- 4:服务器端和客户端解析XML花费资源和时间
JSON:
优点:
- 1:数据格式比较简单,易于读写,格式都是压缩的,占用宽带小.
- 2:易于解析这种语言
- 3:支持多种语言,包括
ActionScript
,C
,C#
,ColdFusion
,Java
,JavaScript
,Perl
,PHP
,Python
,Ruby
等语言服务器端语言,便于服务器端的解析. - 4:因为JSON格式能够直接为服务器端代码使用,大大简化了服务器端和客户端的代码开发量,但是完成的任务不变,且易于维护.
缺点:
- 1:没有XML格式这么推广的深入人心和使用广泛,没有XML那么通用性.
- 2:JSON格式目前在Web Service中推广还属于初级阶段.