前言
在 iOS
开发中,常见的 数据传输
格式有两种:JSON和XML
。
服务器返回客户端的数据,一般都是 JSON格式或XML格式(文件下载除外)
JSON
由于 体积小、传输快速
等优点,逐渐成为了 主流的数据传输格式
。
JSON
在 iOS
中,常见解析方案有以下几种:
性能最好的是使用 苹果原生的框架
: NSJSONSerialization
第三方框架:JSONKit、SBJson、TouchJSON(性能从左到右,越来越差)
JSON格式很像OC中的数组和字典,key必须用双引号
1
| {"name":"张三","age":22}、[{"name":"张三","age":22},{"name":"李四","age":22}]
|
JSON格式
JSON 转 OC
一般从网络请求返回的数据格式是JSON
- 第一个参数:要解析的JSON数据,是NSData类型也就是二进制数据
- 第二个参数:解析JSON的可选配置参数
- NSJSONReadingMutableContainers 解析出来的字典和数组是可变的
- NSJSONReadingFragmentsAllowed 解析出来的对象中的字符串是可变的
- NSJSONReadingMutableLeaves 被解析的数据如果既不是字典也不是数组,那么就使用这个
- 第三个参数:错误信息
1
| NSDictionary * dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
|
OC 转 JSON
- 第一个参数:要转换成JSON数据的OC对象,这里是一个字典
- 第二个参数:NSJSONWritingPrettyPrinted 对转换之后的JSON对象进行排版,无意义
- 第三个参数:错误信息
1
| NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&error];
|
XML
- XML
可扩展标记语言
,是一种数据交互格式,也叫XML文档
- XML 被设计用来
传输和存储数据
构成
常见的XML文档由三部分组成
在XML文档最前面,必须编写一个文档声明,用来声明XML文档的类型
1 2 3 4 5
| // 最简单的声明 <?xml version="1.0" ?>
// 用encoding属性说明文档的字符编码 <?xml version="1.0" encoding="UTF-8" ?>
|
元素
- 一个元素包括了
开始标签和结束标签
,
- 有内容的元素
<name>Tom</name>
;没内容的元素 <from></from>
,可简写成 <from/>
- 元素可嵌套其他元素,不可出现交叉嵌套
属性
一个元素最多可以拥有多个属性,属性值必须用双引号 " "
或 单引号 ' '
括住
1 2 3 4 5 6
| <root> <person id="p1"> <name>Tom</name> <age>24</age> </person> </root>
|
XML 解析的方法
要想从XML中提取信息,就得解析XML,目前针对XML的解析有两种方式:
- SAX:从根元素开始,按照顺序一个元素一个元素的往下解析,可用于解析大、小文件
- DOM:一次性将整个XML文档加载到内存中,适合较小的文件
iOS
中解析 XML
有两种:
解析XML大文件建议用:NSXMLParse、libxml2
解析XML小文件上述三种都可以
NSXMLParse 使用
创建本地xml文件
1 2 3 4 5 6 7
| <?xml version="1.0" encoding="utf-8"?> <clientOauthReturn> <returnCode>RZ001100</returnCode> <returnMessage>会话失效,请重新登录</returnMessage> <authorizationCode></authorizationCode> <tokenId>be9b425801aa4d7e89de79a7d9c10e31</tokenId> </clientOauthReturn>
|
ViewController.m中解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| #import "ViewController.h"
@interface ViewController ()<NSXMLParserDelegate> @property (nonatomic,strong)NSMutableDictionary * mdic; @property (nonatomic,copy)NSString * currentElementName; @end
@implementation ViewController
- (void)viewDidLoad { [super viewDidLoad]; NSString * path = [[NSBundle mainBundle] pathForResource:@"auth" ofType:@"xml"]; NSData * data = [[NSData alloc] initWithContentsOfFile:path options:(NSDataReadingMappedIfSafe) error:nil]; NSXMLParser * parser=[[NSXMLParser alloc] initWithData:data]; parser.delegate = self; [parser parse]; }
// 开始解析XML文档的时候调用 - (void)parserDidStartDocument:(NSXMLParser *)parser { NSLog(@"开始解析XML文档"); } // 开始解析某个元素的时候调用 该方法会调用多次 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict{ NSLog(@"开始解析单个元素:%@", elementName); self.currentElementName = elementName; if ([self.currentElementName isEqualToString:@"returnCode"]) { [self.mdic setObject:@"" forKey:@"returnCode"]; } if ([self.currentElementName isEqualToString:@"returnMessage"]) { [self.mdic setObject:@"" forKey:@"returnMessage"]; } if ([self.currentElementName isEqualToString:@"authorizationCode"]) { [self.mdic setObject:@"" forKey:@"authorizationCode"]; } if ([self.currentElementName isEqualToString:@"tokenId"]) { [self.mdic setObject:@"" forKey:@"tokenId"]; } }
// 解析发现字符串 -(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { NSLog(@""); // 剔除获取的文本中空格和换行 string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; if ([self.currentElementName isEqualToString:@"returnCode"] && string.length > 0) { [self.mdic setObject:string forKey:@"returnCode"]; } if ([self.currentElementName isEqualToString:@"returnMessage"] && string.length > 0) { [self.mdic setObject:string forKey:@"returnMessage"]; } if ([self.currentElementName isEqualToString:@"authorizationCode"] && string.length > 0) { [self.mdic setObject:string forKey:@"authorizationCode"]; } if ([self.currentElementName isEqualToString:@"tokenId"] && string.length > 0) { [self.mdic setObject:string forKey:@"tokenId"]; } }
// 某个元素解析完毕的时候调用 该方法会调用多次 -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{ NSLog(@"单个元素解析完毕"); } // 整个XML文档解析完毕的时候调用 -(void)parserDidEndDocument:(NSXMLParser *)parser{ NSLog(@"整个XML文档解析完毕"); // 主线程 dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"mdic:%@",self.mdic); }); }
#pragma mark -懒加载 - (NSMutableDictionary *)mdic{ if (!_mdic) { _mdic = @{}.mutableCopy; } return _mdic; } @end
|
GDataXML 使用
- GDataXMLDocument:xml解析入口
- GdataXMLElement:保存查找的数据
- GdataXMLNode:保存解析的数据
第一步:集成 GDataXML-HTML
1 2 3 4 5 6 7 8 9
| target 'XML文件解析' do # Comment the next line if you don't want to use dynamic frameworks use_frameworks!
pod 'GDataXML-HTML', '~> 1.4.1'
# Pods for XML文件解析
end
|
第二步:项目中配置
pod 安装 GDataXML
选中target -> Build Settings -> Link Binary With Libraried,搜索添加 libxml2
Header Search Paths 添加 /usr/include/libxml2
Other Linker Flags 添加 -lxml2
引入头文件使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| - (void)GDataParserXML{ // 加载xmlwen文件 NSString *path = [[NSBundle mainBundle]pathForResource:@"xmlText" ofType:@"xml"]; NSURL *url = [NSURL fileURLWithPath:path]; NSData *data = [NSData dataWithContentsOfURL:url]; NSError *error= nil; GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data error:&error]; // 拿到根元素,得到根元素下所有子孙元素 NSArray * elementList =[doc.rootElement elementsForName:@"book"]; for (GDataXMLElement *element in elementList) { NSString *title=((GDataXMLElement *)[[element elementsForName:@"title"] firstObject]).stringValue; NSString *author=((GDataXMLElement *)[[element elementsForName:@"author"] firstObject]).stringValue; NSString *year=((GDataXMLElement *)[[element elementsForName:@"year"] firstObject]).stringValue; NSString *price=((GDataXMLElement *)[[element elementsForName:@"price"] firstObject]).stringValue; NSLog(@"title = %@ author = %@ year = %@ price = %@",title,author,year,price); } }
|