點擊打開下載鏈接iOS,XML/JSON解析 // FInterPreterVC.m // FInterpreter // // Created by lanouhn on 14-9-11. // Copyright (c) 2014年 [email protected] 陳聰雷. All rights reserved. // #import "FInterPreterVC.h" #import "Person.h" #import "GDataXMLNode.h" #import "JSONKit.h" @interface FInterPreterVC ()@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