iOS 網路資料之XML解析

來源:互聯網
上載者:User

iOS 網路資料之XML解析

向伺服器請求資料,那麼資料必須以某個特定的格式存放,然後一方把資料按這種格式組織起來,另一方按相同的方式把資料解析數來,就像是我們人之間講話交流,我們的話會轉變成震動、在空氣中傳播、然後對方的耳朵感受這種震動,然後把震動轉化為話,所以我認為格式的組織是為了更好的傳遞資料。一般網路資料會封裝成兩種格式進行傳遞:XML和json。

1、”解析“:

XML長得和HTML很像,開啟瀏覽器的顯示源碼功能,可以看到一串串的<>標籤,而解析XML也依靠於這些標籤。首先說下我理解的“解析”,不管是XML還是json,實際就是一大段字串,解析就是按XML或json的格式規範把這個字串變成字典或數組,這樣才能自由的擷取裡面的資料。比如:

晴轉多雲微風34 ~ 23℃
weather標籤裡面是”晴轉多雲“,就是說天氣是晴轉多雲,那麼這就是字典裡面的一個鍵值對,weather是鍵,晴轉多雲是值。XML、json和數組字典都是組織資料的東西,“解析”就是把資料從某種組織格式轉為另一種。

2、DOM和SAX:

這是XML的兩種解析方式,DOM是把XML文檔整個的載入,對於這個文檔裡資料的結構都清楚了;然後可以使用XPath直接擷取某個節點;而SAX是從XML頭部逐條逐個標籤的向下讀,遇到一個什麼東西就通知一下,所以它不需要XML文檔已經全部擷取,但是它只管得了當前讀到的地方,前面讀過的就取不到了,所以在結構上不是很清楚,但是相對快速、耗記憶體小。個人覺得DOM解析操作起來更方便一些。

3、關於解析類庫的選擇:

參看文章:iOS平台XML解析類庫對比概述

4、系統的NSXMLParser的使用:

XML資料選擇使用百度天氣介面的資料,地址:http://api.map.baidu.com/telematics/v3/weather?location=%E5%8C%97%E4%BA%AC&ak=5slgyqGDENN7Sy7pw29IUvrZ 。關於天氣介面的配置,可以參考:百度天氣介面

(1)擷取資料:

-(void )getXMLData{    NSString * URLStr = @"http://api.map.baidu.com/telematics/v3/weather?location=%E5%8C%97%E4%BA%AC&ak=5slgyqGDENN7Sy7pw29IUvrZ";    NSURL * url = [NSURL URLWithString:URLStr];    NSURLRequest * request = [[NSURLRequest alloc]initWithURL:url];    _XMLData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];    }

(2)構建NSXMLParser:

-(void )parserXMLData{    _parser = [[NSXMLParser alloc]initWithData:_XMLData];    _parser.delegate = self;    if (![_parser parse]) {        NSLog(@"Parser start error");    }}
這裡是使用NSData對象構建,也可以使用文檔資源地址構建- (id)initWithData:(NSData *)data、使用輸入資料流構建:- (id)initWithStream:(NSInputStream *)stream。調用parse開啟解析。需要設定委派物件,這樣在解析到某個元素變遷或是字元的時候,會讓委派物件調用委託方法,而就是在這些方法裡面進行資料的處理。

(3)委託方法:
-(void )parserDidStartDocument:(NSXMLParser *)parser{  //開始解析文檔是調用    NSLog(@"doucment start");}-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{  //每次解析到一個標籤的時候調用,例如上面晴轉多雲中的標籤    _currentElement = elementName; //把當前的標籤儲存下來,便於下面方法裡判斷    if ([_currentElement isEqualToString:@"weather_data"]) { //當開始解析weather_data這個標籤的時候構建數組,用於儲存多天的天氣資訊。        _weatherArray = [[NSMutableArray alloc]init];    }else if ([_currentElement isEqualToString:@"date"]&&_weatherArray){//因為date標籤是每一天天氣資訊的開始變遷,所以在解析到date標籤的時候構建一個字典,用來儲存某一天的天氣資訊,並且加入到_weatherArray裡面        NSMutableDictionary * oneDayWeather = [[NSMutableDictionary alloc]init];        [_weatherArray addObject:oneDayWeather];    }}-(void )parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{ //每次解析到一個字串,在XML文檔裡,除了標籤,就是資料,而資料有些數字串,所以字串資料時會調用這個方法,例如上面的晴轉多雲中的晴轉多雲。    string = [string stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" \n\r"]]; //通過這個方法去掉空格、換行字串,保證把有用的字串存進來    if (_weatherArray&&string.length>0) {        if ([_currentElement isEqualToString:@"date"]) { //使用_currentElement的值來判斷當前是處於哪一個標籤內部            NSMutableDictionary * oneDayWeather = _weatherArray.lastObject; //因為SAX解析從上到下,所以lastObject就是最新的一個字典,也就是當前需要存入資料的字典            [oneDayWeather setObject:string forKey:@"date"];        }else if ([_currentElement isEqualToString:@"dayPictureUrl"]){            NSMutableDictionary * oneDayWeather = _weatherArray.lastObject;            [oneDayWeather setObject:string forKey:@"dayPictureUrl"];        }else if ([_currentElement isEqualToString:@"nightPictureUrl"]){            NSMutableDictionary * oneDayWeather = _weatherArray.lastObject;            [oneDayWeather setObject:string forKey:@"nightPictureUrl"];        }else if ([_currentElement isEqualToString:@"weather"]){            NSMutableDictionary * oneDayWeather = _weatherArray.lastObject;            [oneDayWeather setObject:string forKey:@"weather"];        }else if ([_currentElement isEqualToString:@"wind"]){            NSMutableDictionary * oneDayWeather = _weatherArray.lastObject;            [oneDayWeather setObject:string forKey:@"wind"];        }else if ([_currentElement isEqualToString:@"temperature"]){            NSMutableDictionary * oneDayWeather = _weatherArray.lastObject;            [oneDayWeather setObject:string forKey:@"temperature"];        }    }}-(void )parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock{ //和上面的字串類似,有些資料不是字串,而是位元組,這裡就是NSData對象    NSLog(@"%@",[[NSString alloc]initWithData:CDATABlock encoding:NSUTF8StringEncoding]);}-(void )parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{ // 當解析到一個標籤的結束的時候調用,每一個標籤都是開頭、結尾兩個成對存在的,例如晴轉多雲中的和,當解析到的時候就是一個標籤的結束,也就會調用這個方法。    //NSLog(@" elementName : %@ , namespaceURI : %@ , qualifiedName : %@ ",elementName,namespaceURI,qName);}-(void )parserDidEndDocument:(NSXMLParser *)parser{  //這是文檔整個解析完畢的時候調用    NSLog(@"document end");        NSLog(@"%@",_weatherArray);}
上面列舉了一些解析過程中調用的委託方法,還有許多其他方法,參考文檔中NSXMLParserDelegate。似乎方法很詳細,把解析過程的每個細節的考慮到了,但是感覺把XML中的資料合理的存放到數組字典裡,真不是件容易的事,不想json,一句話就搞定了。SAX解析最大的不便是,當解析到某個標籤的時候,你不知道它上一層的標籤是什麼,更不知道上上層的標籤是什麼,也就是說沒有東西能告訴你整個文檔的結構是什麼樣的。上面的例子是將連結中獲得的天氣XML文檔中天氣的部分取出來放進數組_weatherArray裡面,也就是...這個標籤內的內容。

SAX解析總的來說,不是很方便,如果資料的階層比較複雜,處理起來會很麻煩,所以要考慮DOM解析和json格式。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.