<a target=_blank href="http://download.youkuaiyun.com/detail/vaercly/7908319">点击打开下载链接iOS,XML/JSON解析</a>
// FInterPreterVC.m
// FInterpreter
//
// Created by lanouhn on 14-9-11.
// Copyright (c) 2014年 vaercly@163.com 陈聪雷. All rights reserved.
//
#import "FInterPreterVC.h"
#import "Person.h"
#import "GDataXMLNode.h"
#import "JSONKit.h"
@interface FInterPreterVC ()<NSXMLParserDelegate>
@property (nonatomic, retain) NSMutableArray *arr;//用来存储person对象
@property (nonatomic, retain) Person *per;//用来存储信息
@property (nonatomic, retain) NSString *str;//存储读到的字符串
@end
@implementation FInterPreterVC
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
/**
* 解析:按照一种约定好的格式(假象), 有后台开发人员, 按照格式存数据, 由前端按照格式取数据(谨记: 这种格式是由后台开发人员决定的, 我们无权决定)
解析的本质: 按照约定好的格式取出我们想要数据的过程
当今比较流行的格式:XML和JSON格式
XML解析两种解析原理:
SAX解析:基于事件回调的解析机制, 就是使用协议以及代理. SAX解析是逐行解析, 读入数据时只读入一行, 一行一行的解析, 所以SAX解析占用内存较小, 适合于大数据解析
DOM解析:一次性将内容全部读入内存, 将内容读成树形结构, 逐层解析, 适合小数据解析
*/
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
UILabel *XMLLabel = [[UILabel alloc] initWithFrame:CGRectMake(110, 30, 100, 30)];
XMLLabel.text = @"XML解析";
XMLLabel.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:XMLLabel];
[XMLLabel release];
UILabel *JSONLabel = [[UILabel alloc] initWithFrame:CGRectMake(110, 200, 100, 30)];
JSONLabel.text = @"JSON解析";
JSONLabel.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:JSONLabel];
[JSONLabel release];
NSArray *titles = @[@"SAX解析",@"Dom解析第一种方式",@"Dom解析第二种方式",@"系统解析",@"字符串解析",@"数组解析",@"字典解析",@"Data解析"];
NSArray *methods = @[@"handleSAX:",@"handleDomBtn1:",@"handleDomBtn2:",@"handleSystemJSON:",@"handleStrBtn:",@"handleArrBtn:",@"handleDicBtn:",@"handleDataBtn:"];
CGFloat height = 70;
for (int i = 0; i < 8; i++) {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
btn.frame = CGRectMake(60, height, 200, 30);
btn.backgroundColor = [UIColor greenColor];
[btn setTitle:titles[i] forState:UIControlStateNormal];
SEL selector = NSSelectorFromString(methods[i]);
[btn addTarget:self action:selector forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
if (i == 2) {
height = 200;
}
height += 40;
}
UILabel *text = [[UILabel alloc] initWithFrame:CGRectMake(110, 470, 100, 30)];
text.text = @"加油!";
text.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:text];
[text release];
}
//SAX解析
- (void)handleSAX:(UIButton *)btn
{
//1 获取解析的文件路径
NSString *xmlPath = [[NSBundle mainBundle] pathForResource:@"Person" ofType:@"xml"];
//2 根据文件路径初始化NSData对象
NSData *data = [NSData dataWithContentsOfFile:xmlPath];
//3 创建解析工具对象
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
//4 设置代理
parser.delegate = self;
//5 开始解析
[parser parse];
}
#pragma mark - NSXMLParserDetegate
//当读取到开始标签时触发
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
NSLog(@"start %@", attributeDict);
//当数据存储到开始标签的属性中时, 处理方式
if ([elementName isEqualToString:@"Persons"]) {
//为数组开辟空间
self.arr = [NSMutableArray array];
} else if ([elementName isEqualToString:@"person"]) {
//为person对象开辟空间
self.per = [[[Person alloc] init] autorelease];
[self.arr addObject:self.per];
} else if ([elementName isEqualToString:@"name"]) {
self.per.name = attributeDict[@"name"];
} else if ([elementName isEqualToString:@"gender"]) {
self.per.gender = attributeDict[@"gender"];
} else if ([elementName isEqualToString:@"age"]) {
self.per.age = attributeDict[@"age"];
} else if ([elementName isEqualToString:@"phoneNumber"]) {
self.per.phoneNumber = attributeDict[@"phoneNumber"];
} else if ([elementName isEqualToString:@"imageName"]) {
self.per.imageName = attributeDict[@"imageName"];
}
//当数据存储到开始标签以及结束标签中时, 处理方式
/*
if ([elementName isEqualToString:@"Persons"]) {
//为数组开辟空间
self.arr = [NSMutableArray array];
} else if ([elementName isEqualToString:@"person"]) {
//为perosn对象开辟空间
self.per = [[[Person alloc] init] autorelease];
}
*/
}
//当读到标签后的内容时触发
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
// NSLog(@"content %@", string);
//保存读取到得数据
// self.str = string;
}
//当读取到结束标签时触发
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
NSLog(@"end %@", elementName);
/*
if ([elementName isEqualToString:@"name"]) {
self.per.name = self.str;
} else if ([elementName isEqualToString:@"gender"]) {
self.per.gender = self.str;
} else if ([elementName isEqualToString:@"age"]) {
self.per.age = self.str;
} else if ([elementName isEqualToString:@"phoneNumber"]) {
self.per.phoneNumber = self.str;
} else if ([elementName isEqualToString:@"imageName"]) {
self.per.imageName = self.str;
} else if ([elementName isEqualToString:@"person"]) {
//当读到person的结束标签时, person对象已经赋值完毕, 存储到数组中
[self.arr addObject:self.per];
}
*/
}
//当解析完毕之后触发
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
NSLog(@"game over");
NSLog(@"%@", self.arr);
}
//DOM解析第一种方式
/**
* DOM解析使用Google提供的一个开源高效的解析工具GDataXMLNode, 它的效果要比NSXMLParser要快10倍
使用方式:
1 先导入系统动态链接库 libxml2.2.dylib
2 在buildSettings中的Header Search Path中添加/usr/include/libxml2
3 在buildSettings中的Other Linker Flags中添加-lxml2
*/
- (void)handleDomBtn1:(UIButton *)btn
{
//1 获取解析文件的路径
NSString *xmlPath = [[NSBundle mainBundle] pathForResource:@"Person" ofType:@"xml"];
//2 初始化xml字符串
NSString *xmlStr = [NSString stringWithContentsOfFile:xmlPath encoding:NSUTF8StringEncoding error:nil];
//3 初始化一个GDataXMLDocument对象, 因为解析时所有的内容都是从该对象中读取(所以需要将要解析的内容存在该对象中)
GDataXMLDocument *document = [[GDataXMLDocument alloc] initWithXMLString:xmlStr options:0 error:nil];
//4 获取根节点
GDataXMLElement *rootElement = [document rootElement];
//5 获取根节点的所有子节点
NSArray *personElements = [rootElement elementsForName:@"person"];
//6 先获取数组得到每一个person节点, 然后再得到perosn节点下的子节点
for (GDataXMLElement *element in personElements) {
//获取perosn节点下的name节点
GDataXMLElement *nameElement = [[element elementsForName:@"name"] firstObject];
//获取perosn节点下的gender节点
GDataXMLElement *genderElement = [[element elementsForName:@"gender"] firstObject];
//获取perosn节点下的age节点
GDataXMLElement *ageElement = [[element elementsForName:@"age"] firstObject];
//获取perosn节点下的imageName节点
GDataXMLElement *imageNameElement = [[element elementsForName:@"imageName"] firstObject];
//获取perosn节点下的phoneNumber节点
GDataXMLElement *phoneNumberElement = [[element elementsForName:@"phoneNumber"] firstObject];
//1 获取开始标签与结束标签的值
/*
NSString *name = [nameElement stringValue];
NSString *gender = [genderElement stringValue];
NSString *age = [ageElement stringValue];
NSString *imageName = [imageNameElement stringValue];
NSString *phoneNumber = [phoneNumberElement stringValue];
NSLog(@"=======%@ %@ %@ %@ %@", name, gender, age, imageName, phoneNumber);
*/
//2 获取表现中属性中存储的数据
//属性对应的类是GDataXMLNode
GDataXMLNode *nameNode = [nameElement attributeForName:@"name"];
GDataXMLNode *genderNode = [genderElement attributeForName:@"gender"];
GDataXMLNode *ageNode = [ageElement attributeForName:@"age"];
GDataXMLNode *imageNameNode = [imageNameElement attributeForName:@"imageName"];
GDataXMLNode *phoneNumberNode = [phoneNumberElement attributeForName:@"phoneNumber"];
NSString *name = [nameNode stringValue];
NSString *gender = [genderNode stringValue];
NSString *age = [ageNode stringValue];
NSString *phoneNumber = [phoneNumberNode stringValue];
NSString *imageName = [imageNameNode stringValue];
NSLog(@"%@ %@ %@ %@ %@", name, gender, age, phoneNumber, imageName);
}
}
- (void)handleDomBtn2:(UIButton *)btn
{
//1 获取解析文件的路径
NSString *xmlPath = [[NSBundle mainBundle] pathForResource:@"Person" ofType:@"xml"];
//2 初始化xml字符串
NSString *xmlStr = [NSString stringWithContentsOfFile:xmlPath encoding:NSUTF8StringEncoding error:nil];
//3 初始化一个GDataXMLDocument对象, 因为解析时所有的内容都是从该对象中读取(所以需要将要解析的内容存在该对象中)
GDataXMLDocument *document = [[GDataXMLDocument alloc] initWithXMLString:xmlStr options:0 error:nil];
/**
* XPath 只要给定相对路径即可, 如://name, 只要能够到达name, 都可以把name获取到
*/
//4 获取所有的name节点
NSArray *nameElements = [document nodesForXPath:@"//name" error:nil];
//获取所有的gender节点
NSArray *genderElements = [document nodesForXPath:@"//gender" error:nil];
//获取所有的age节点
NSArray *ageElements = [document nodesForXPath:@"//age" error:nil];
//获取所有的imageName节点
NSArray *imageNameElements = [document nodesForXPath:@"//imageName" error:nil];
//获取所有的phoneNumber节点
NSArray *phoneNumberElements = [document nodesForXPath:@"//phoneNumber" error:nil];
//通过循环取出每个节点
for (int i = 0; i < 3; i++) {
GDataXMLElement *nameElement = nameElements[i];
GDataXMLElement *genderElement = genderElements[i];
GDataXMLElement *ageElement = ageElements[i];
GDataXMLElement *imageNameElement = imageNameElements[i];
GDataXMLElement *phoneNumberElement = phoneNumberElements[i];
NSString *name = [nameElement stringValue];
NSString *gender = [genderElement stringValue];
NSString *age = [ageElement stringValue];
NSString *imageName = [imageNameElement stringValue];
NSString *phoneNumber = [phoneNumberElement stringValue];
NSLog(@"-------%@ %@ %@ %@ %@", name, gender, age, imageName, phoneNumber);
}
}
//系统的解析方式
- (void)handleSystemJSON:(UIButton *)btn
{
//1 获取文件路径
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Student" ofType:@"json"];
//2 初始化NSData对象
NSData *data = [NSData dataWithContentsOfFile:filePath];
//3 解析
NSMutableArray *arr = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(@"%@", arr);
}
//JSONKit类的解析方式
/**
* 对于JSONKit 提供的解析方式,是为NSString,NSData添加分类的方式,在分类中添加了解析的方法.效率仅次于系统的.
将json格式数据解析成NSArray,NSDictionary.
而为NSArray,NSDictionary添加的分类的方法,则是将OC的对象,转化为JSON格式字符串.
*
*/
- (void)handleStrBtn:(UIButton *)btn
{
//1 获取文件路径
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Student" ofType:@"json"];
//2 初始化NSString对象
NSString *jsonStr = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
//3 解析
NSArray *arr = [jsonStr objectFromJSONString];
NSLog(@"%@", arr);
}
- (void)handleArrBtn:(UIButton *)btn
{
//1 将OC的数组转换为json格式化字符串
NSArray *arr = @[@1,@"bb",@"cc",@"dd",@"ee"];
//转化
NSString *jsonStr = [arr JSONString];
NSLog(@"%@", jsonStr);
//2 解析
NSString *str = [jsonStr objectFromJSONString];
NSLog(@"%@", str);
}
- (void)handleDicBtn:(UIButton *)btn
{
//1 将OC的字典转换为json格式化字符串
NSDictionary *dic = @{@"name":@1,@"gender":@"man",@"age":@"18"};
//转化
NSString *jsonStr = [dic JSONString];
NSLog(@"%@", jsonStr);
//2 解析
NSString *str = [jsonStr objectFromJSONString];
NSLog(@"%@", str);
}
- (void)handleDataBtn:(UIButton *)btn
{
//1 获取文件路径
NSString *fileParth = [[NSBundle mainBundle] pathForResource:@"Student" ofType:@"json"];
//2 初始化NSData对象
NSData *jsonData = [NSData dataWithContentsOfFile:fileParth];
//3 解析
NSArray *arr = [jsonData objectFromJSONData];
NSLog(@"%@", arr);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
- (void)dealloc
{
self.arr = nil;
self.per = nil;
self.str = nil;
[super dealloc];
}
@end