解析:從事先約定好的格式中提取數(shù)據(jù)挚币。這種格式是前端開發(fā)人員和后臺約定好的输硝,約定獲取的數(shù)據(jù)是什么格式的开瞭,就是用什么格式的解析方式(一般都是前端開發(fā)人員聽從后臺的)
解析的前提:按照約定好的格式录煤,數(shù)據(jù)提供方按照格式提供數(shù)據(jù)捞稿、數(shù)據(jù)獲取方按照格式獲取數(shù)據(jù)
解析常見的為XML解析又谋、 JSON解析
JSON解析
{
"reason":"success",
"result":[
{
"movieId":"216609",
"movieName":"詭八樓",
"pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583083"
},
{
"movieId":"216391",
"movieName":"摩登森林之美食總動員",
"pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583246"
},
{
"movieId":"216162",
"movieName":"龜兔再跑",
"pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583181"
}
......
],
"error_code":0
}
上面為JSON格式數(shù)據(jù)拼缝,是一個大字典,字典的鍵值對中的值又包括數(shù)組彰亥。數(shù)組中又包含好多個字典咧七,每個字典的鍵值對就是我們需要取出的數(shù)據(jù)
json文件有兩種結(jié)構(gòu):
對象:"名稱/值"對的集合。不同的語言中任斋,它被理解為對象继阻,記錄,結(jié)構(gòu)废酷,字典瘟檩,哈希表,有鍵列表澈蟆,或者關(guān)聯(lián)數(shù)組墨辛。以"{" 開始, 以"}" 結(jié)束, 是"名稱/值"對的集合趴俘。名稱和值中間用":"隔開睹簇。多個"名稱/值"對之間用 ", " 隔開
數(shù)組: 值得有序列表。在大部分語言中寥闪,它被理解為數(shù)組太惠。以"[" 開始, 以"]" 結(jié)束橙垢,中間是數(shù)據(jù)垛叨。數(shù)據(jù)以 ", " 分隔
JSON中的數(shù)據(jù)類型:字符串,數(shù)值柜某,BOOL嗽元,對象,數(shù)組
JSON解析工具:JSONKit喂击、 NSJSONSerialization撒强、 TouchJSON 和SBJSON等夯辖,其中NSJSONSerialization是系統(tǒng)提供的解析類锹漱,其解析效率是最高的
其中關(guān)于其他第三方的JSON解析工具 在http://www.reibang.com/p/a54d367adb2a 里面會有講解腋逆,這里只是分享了系統(tǒng)自帶的JSON解析工具NSJSONSerialization
NSJSONSerialization 解析步驟:
1.得到j(luò)son文件,并且轉(zhuǎn)換為data類型
step1.1文件路徑
NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"MovieList" ofType:@"text"];
step1.2轉(zhuǎn)化為 nsdata類型
NSData *jsonData = [NSData dataWithContentsOfFile:jsonPath];//根據(jù)路徑獲取data類型數(shù)據(jù)
step1.3解析json 數(shù)據(jù) jsonkit sbjson touchjson 三種解析第三方 但是還是系統(tǒng)提供的json解析更好用
NSError *error = nil;
NSDictionary *resultDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragmentserror:&error]; //系統(tǒng)提供的json解析數(shù)據(jù)的工具
//error錯誤 里面包含了解析是處的錯誤监嗜,一般打印是為了驗證錯誤點
NSLog(@"%@", error);
2.判斷解析獲得的數(shù)據(jù)是否正常(是否是我們想要的數(shù)據(jù)) //這一步是在驗證谐檀,真正開發(fā)時,可以不使用
if (resultDic) { //如果解析的數(shù)據(jù)不為空
//判斷當前的對象是否支持json格式
if ([NSJSONSerialization isValidJSONObject:resultDic]) {
NSData *strData = [NSJSONSerialization dataWithJSONObject:resultDic options:NSJSONWritingPrettyPrinted error:nil];
//將data 轉(zhuǎn)換為字符串
if (strData != nil) {
NSString *str = [[NSString alloc] initWithData:strData encoding:NSUTF8StringEncoding];
NSLog(@"%@", str);
}
}
}
XML解析
<?xml version="1.0" encoding="utf-8"?> <!--此行包含XML的版本信息和編碼格式-->
<students><!--這是開始標簽裁奇,也就是根節(jié)點-->
<student attribute = "七班班寶" position = "bu"><!--student為根節(jié)點的子節(jié)點桐猬,name節(jié)點的父節(jié)點, attribute是它的屬性-->
<name>趙威</name><!--李帥為name節(jié)點的值-->
<sex>無</sex>
<age>14</age>
</student>
<student attribute = "七班班長">
<name>鵬鵬</name>
<sex>隨條件改變</sex>
<age>17</age>
</student>
<student attribute = "banzhangtamei">
<name>lisi</name>
<sex>隨他呢</sex>
<age>33</age>
</student>
</students><!--節(jié)點的結(jié)束標簽都是以/加標簽名稱組成 -->
上面為XML格式數(shù)據(jù)刽肠。
XML: Extensible Markup language (可拓展標記語言)溃肪,主流數(shù)據(jù)格式之一免胃,可以用來存儲和傳輸數(shù)據(jù)
節(jié)點:使用一對標簽表示:起始和結(jié)束標簽 <節(jié)點名> 數(shù)據(jù)或其他節(jié)點</節(jié)點名>
XML數(shù)據(jù)結(jié)構(gòu):有且只有一個根節(jié)點,如上面代碼中的students惫撰, 但是在根節(jié)點中可以嵌套好多子節(jié)點羔沙,子節(jié)點可以作為父節(jié)點嵌套下一級子節(jié)點 如<student> <name> </name> </student> student 作為父節(jié)點students的子節(jié)點,又是name節(jié)點的父節(jié)點
節(jié)點中可以有值厨钻,存儲在一對標簽中 如 <name>趙威</name> 節(jié)點的值就是 趙威
這樣按照層級的層次把數(shù)據(jù)存儲在節(jié)點中扼雏,獲取數(shù)據(jù)也是調(diào)取節(jié)點中的數(shù)據(jù)
XML解析的作用:數(shù)據(jù)交換 內(nèi)容管理 用作配置文件
XML解析又分為SAX解析和DOM解析
XML解析之SAX解析
SAX: Simple API for XML±蚱玻基于事件驅(qū)動的解析方式呢蛤,逐行進行解析數(shù)據(jù)(采用協(xié)議回調(diào)機制)。
SAX解析使用的類:NSXMLParser 棍郎。NSXMLPraser是系統(tǒng)自帶的XML解析類,采用SAX方式解析數(shù)據(jù)银室。
解析過程由NSXMLPraserDelegate協(xié)議方法回調(diào)
解析過程:開始標簽->取值->結(jié)束標簽->取值
@interface RootViewController ()<NSXMLParserDelegate>//簽協(xié)議
@property (nonatomic, strong) NSMutableDictionary *dic;//用來student節(jié)點中的值
@property (nonatomic ,strong) NSMutableArray *allDataArray;//用來盛放所有的student節(jié)點轉(zhuǎn)換的字典
@property (nonatomic, strong) NSMutableString *valueString;//用來拼接節(jié)點中間的值
@end
//得到需要解析的數(shù)據(jù) 獲取數(shù)據(jù)文件所在的地址
NSString *saxPath = [[NSBundle mainBundle] pathForResource:@"XMLDemo" ofType:@"xml"];
//獲取data
NSData *saxData = [NSData dataWithContentsOfFile:saxPath];
//創(chuàng)建sax解析的工具類對象
NSXMLParser *saxParser = [[NSXMLParser alloc] initWithData:saxData];
//指定代理
saxParser.delegate = self;
//開始解析 sax解析是一個同步的過程
BOOL isParser = [saxParser parse];
//判斷解析成功
if(isParser)
NSLog(@"解析完成");
else
NSLog(@"解析失敗");
#pragma mark --sax解析代理方法
//開始解析
- (void)parserDidStartDocument:(NSXMLParser *)parser {
NSLog(@"開始解析");
//初始化數(shù)組(遍歷構(gòu)造器) 在開始解析里面初始化保存數(shù)據(jù)的數(shù)組
self.allDataArray = [NSMutableArray array];
}
//開始解析某個節(jié)點
/*
elementName:標簽名稱
namespaceURI:命名空間指向的鏈接
qualifiedName:命名空間的名稱
attributtes:節(jié)點的所有屬性(可以多個)
*/
- (void)parser:(NSXMLParser *)parser didStartElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName attributes:(nonnull NSDictionary<NSString *,NSString *> *)attributeDict {
NSLog(@"開始解析%@節(jié)點", elementName);
//當開始解析student子節(jié)點的時候涂佃,就應(yīng)該初始化字典,因為一個字典就對應(yīng)著一個學生的信息
//每解析一個student蜈敢,就初始化一次
if ([elementName isEqualToString:@"student"]) {
self.dic = [NSMutableDictionary dictionary];
}
}
//獲取節(jié)點之間的值
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
NSLog(@"取值---%@", string);
// if(self.valueString){//說明有值
// [self.valueString appendString:string];
// }else{
// self.valueString = [NSMutableString stringWithString:string];
// }
//這里會把空格覆蓋掉
if (string != nil) {
self.valueString = [NSMutableString stringWithString:string];
}
}
//某個節(jié)點結(jié)束取值
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
NSLog(@"結(jié)束%@節(jié)點的解析", elementName);
if ([elementName isEqualToString:@"name"]) {//說明name節(jié)點已經(jīng)取值結(jié)束
[self.dic setObject:self.valueString forKey:elementName];
}
if ([elementName isEqualToString:@"age"]) {
[self.dic setObject:self.valueString forKey:elementName];
}
if ([elementName isEqualToString:@"sex"]) {
[self.dic setObject:self.valueString forKey:elementName];
}
// [self.dic setObject:self.valueString forKey:elementName];
if ([elementName isEqualToString:@"student"]) {//一個student已經(jīng)解析完畢
[self.allDataArray addObject:self.dic]; //把studnet的字典添加到數(shù)組中
}
self.valueString = nil;
}
//結(jié)束解析 在結(jié)束解析協(xié)議方法中內(nèi)獲取全部的數(shù)據(jù)
- (void)parserDidEndDocument:(NSXMLParser *)parser {
//就可以使用解析完成的數(shù)據(jù)
NSLog(@"%@", self.allDataArray);
NSLog(@"整個解析結(jié)束");
}
//報告不可恢復的解析錯誤
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
NSLog(@"解析出現(xiàn)錯誤:%@", parseError);
}
XML解析之DOM解析
DOM: Document Object Model(文檔對象類型)辜荠。DOM方式解析XML時,讀入整個XML文檔并構(gòu)建一個駐留內(nèi)存的樹結(jié)構(gòu)(節(jié)點數(shù)),通過遍歷節(jié)點樹結(jié)構(gòu)可以檢索任意XML節(jié)點抓狭,讀取他的屬性和值伯病。而且通常情況下,可以借助XPath,直接查詢XML節(jié)點否过。
DOM是基于文檔的解析方式午笛。
DOM解析需要導入的庫 libxml2.dylib(ios7之后改為libxml2.tdb) GDataXMLNode
GDataXMLNode是Google提供的開元XML解析類,對libxml2.tdb進行了Object-C的封裝苗桂,能對較小或中等的xml文檔進行讀寫操作并且支持XPath語法
使用GDataXMLNode使用方法
1.獲取GDataXMLNode.h/m文件药磺,將GDataXMLNode.h/m文件添加到工程中
2.向工程中增加"libxml2.dylib(ios7之后改為libxml2.tdb) "動態(tài)庫
3.在工程的"Build Settings"頁中找到"Header Search Path"項,添加/usr/include/libxml2
4.導入"GDataXMLNode.h"文件到頭文件中煤伟,如工程能編譯通過癌佩,則說明GDataXMLNode添加成功
解析過程
//用來盛放所有的字典
NSMutableArray *datasourse = [NSMutableArray array];
//得到需要解析的數(shù)據(jù)(xml文件)
NSString *xmlPath = [[NSBundle mainBundle] pathForResource:@"XMLDemo" ofType:@"xml"];
//轉(zhuǎn)換為NSData類型
NSData *xmlData = [NSData dataWithContentsOfFile:xmlPath];
//構(gòu)建document文檔對象
NSError *error = nil;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];//options:的值為0,這個是預留的
//找到根節(jié)點,就是students
GDataXMLElement *rootElement = [doc rootElement];
//找到根節(jié)點的所有子節(jié)點,就是所有的student
NSArray *allSubNotes = [rootElement elementsForName:@"student"];
//找到student節(jié)點的所有子節(jié)點
for (GDataXMLElement *item in allSubNotes) {
//每次循環(huán)開始的時候便锨,說明是一個新的student節(jié)點围辙,我們需要字典來盛放他所有的值
//防止引用計數(shù)加一,使用初始化方法
NSLog(@"%@", item.attributes[0]);
NSMutableDictionary *studentDic = [NSMutableDictionary dictionary];
//得到name節(jié)點
NSArray *nameArray = [item elementsForName:@"name"];
// GDataXMLElement *nameElement = [nameArray objectAtIndex:0];
GDataXMLElement *nameElement = [nameArray firstObject];
//取值
NSString *name = [nameElement stringValue];
[studentDic setObject:name forKey:@"name"];
//取出sex
NSArray *sexArray = [item elementsForName:@"sex"];
GDataXMLElement *sexElement = [sexArray firstObject];
NSString *sex = [sexElement stringValue];
[studentDic setObject:sex forKey:@"sex"];
//取出age
NSArray *ageArray = [item elementsForName:@"age"];
GDataXMLElement *ageElement = [ageArray firstObject];
//取值
NSString *age = [ageElement stringValue];
[studentDic setObject:age forKey:@"age"];
//將字典添加到可變數(shù)組中
[datasourse addObject:studentDic];
}
SAX解析和DOM解析的區(qū)別:
SAX只能讀不能寫放案,DOM解析不知能讀姚建,還能寫(增加節(jié)點)
如果文檔小一些,DOM解析效率更高一些
DOM解析基于文檔卿叽,SAX解析基于事件
如果數(shù)據(jù)量相同時桥胞,DOM解析效率更高
SAX解析是逐行解析恳守,DOM解析是整個文檔來操作的
數(shù)據(jù)量比較大時,適用于SAX解析
JSON解析和DOM解析的優(yōu)缺點
XML優(yōu)缺點
優(yōu)點:
1.格式統(tǒng)一贩虾,符合標準
2.容易與其他系統(tǒng)進行遠程交互催烘,數(shù)據(jù)共享比較方便
缺點:
1.XML格式文件龐大,格式復雜缎罢,傳輸暫用寬帶
2.服務(wù)器端和客戶端都需要花費大量代碼來維護XML伊群,不論服務(wù)器端還是客戶端都使代碼變得異常復雜和不容易維護
3.刻畫段不同瀏覽器之間解析XML的方式不一致,需要重復編寫很多代碼
4.服務(wù)器端和客戶端解析MXL花費資源和時間
JSON優(yōu)缺點
優(yōu)點:
1.數(shù)據(jù)格式比較簡單策精,易于讀寫舰始,格式都是壓縮的,占用帶寬小咽袜。
2.易于解析這種語言丸卷。
3.支持多種語言,包括ActionScrip, C, C#, ColdFusion, Java, JavaScript, Perl, PHP, Python, Ruby等語言服務(wù)器端語言询刹,便于服務(wù)器端的解析
4.因為JSON格式能夠直接為服務(wù)器端代碼使用谜嫉,大大簡化了服務(wù)器端和客戶端的代碼開發(fā)量,大師完成的任務(wù)不變凹联,且易于維護沐兰。
缺點:
1.沒有XML格式這么推廣的深入人心和使用廣泛,沒有XML那么通用性蔽挠。
2.JSON格式目前在Web Service中推廣還屬于初級階段
比較 :
xml在布局文件比json強太多住闯,但是json更便于傳輸
xml是可拓展的語言,隨便往里面添加標簽澳淑,標簽名字可以隨便改變