xml與json的對比,前面文章已經提供參考,至於xml的語法結構也不在這詳述。 直奔iOS中解析xml的方法。
iOS中的XML解析(Dom和SAX)
Dom方式使用的是文檔對象模型解析,它首先要將xml文件整個讀入內存中,然後再來構建Dom對象,在DOM對象裡,xml文件中的所有元素都可以當做節點(Node)對象來處理。這種方式優點是方便對文檔進行增加、刪除、修改、添加等操作,缺點是它首先要將整個文件讀入內存中在解析,如果文件大。會很消耗內存,並且它的執行速度慢。
SAX解析XML文件采用事件驅動的方式進行,也就是說,SAX是逐行掃描文件,遇到符合條件的設定條件後就會觸發特定的事件,回調你寫好的事件處理程序。使用SAX的優勢在於其解析速度較快,占用內存較少(相對於DOM而言)。而且SAX在解析文件的過程中得到自己需要的信息後可以隨時終止解析,並不一定要等文件全部解析完畢。凡事有利必有弊,其劣勢在於SAX采用的是流式處理方式,當遇到某個標簽的時候,它並不會記錄下以前所遇到的標簽,也就是說,在處理某個標簽的時候,所能夠得到的信息就是標簽的名字和屬性,至於標簽內部的嵌套結構,上層標簽、下層標簽以及其兄弟節點的名稱等等與其結構相關的信息都是不得而知的。實際上就是把XML文件的結構信息丟掉了,如果需要得到這些信息的話,只能你自己在程序裡進行處理了。所以相對DOM而言,SAX處理XML文檔沒有DOM方便,SAX處理的過程相對DOM而言也比較復雜。
總結:DOM:一次性將整個XML文檔加載進內存,比較適合解析小文件
SAX:SAX采用事件驅動,從根元素開始,按順序一個元素一個元素往下解析,比較適合解析大文件。
解析方法:
蘋果原生
NSXMLParser:SAX方式解析,使用簡單
第三方框架
libxml2:純C語言,默認包含在iOS SDK中,同時支持DOM和SAX方式解析
GDataXML:DOM方式解析,由Google開發,基於libxml2
XML解析方式的選擇建議
大文件:NSXMLParser、libxml2
小文件:GDataXML
GDataXML:
常用的類
GDataXMLDocument:代表整個XML文檔
GDataXMLElement:代表文檔中的每個元素
常用方法:
elementsForName:根據元素名稱得到元素節點
attributeForName:方法可以獲得屬性值
更多的操作xml的方法和屬性,查閱GDataXMLNode.h
使用步驟:
1、下載GDataXMLNode ,下載地址:http://download.csdn.net/detail/zhixinhuacom/9417644,並 解壓將其中的GDataXMLNode.h 和 GDataXMLNode.m文件拖到項目中。
2、由於GDataXML基於libxml2庫,因此要導入libxml2
3、設置libxml2的頭文件搜索路徑(為了能找到libxml2庫的所有頭文件)
在Head Search Path中加入/usr/include/libxml2
4、設置鏈接參數(自動鏈接libxml2庫)
在Other Linker Flags中加入-lxml2
5、如果報arc錯誤,則設置GDataXML編譯參數
6、導入#import "GDataXMLNode.h" 頭文件就可以使用了。
例子:
解析下面格式的xml
-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent *)event{ NSURL *url = [NSURL URLWithString:@"http://localhost:8080/myService/video?type=XML"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) { //1、加載xml數據 GDataXMLDocument *document = [[GDataXMLDocument alloc]initWithData:data options:0 error:nil]; //2、獲取xml根元素(videos) GDataXMLElement *root = document.rootElement; // //元素子節點個數(不包括子節點下的節點) // NSInteger childCount = root.childCount; // //元素名稱 // NSString *elementName = root.name; // //節點內容字符串 // NSString *xmlStr = root.XMLString; // NSLog(@"childCount=%ld\nelementName=%@\nxmlStr=%@",childCount,elementName,xmlStr); //3、獲取根元素的所有video元素 NSArray *elements = [root elementsForName:@"video"]; for (GDataXMLElement *element in elements) { //4、獲取屬性植 NSString *idStr = [element attributeForName:@"id"].stringValue; NSString *name = [element attributeForName:@"name"].stringValue; NSString *length = [element attributeForName:@"length"].stringValue; NSString *image = [element attributeForName:@"image"].stringValue; NSString *url = [element attributeForName:@"url"].stringValue; NSLog(@"id=%@",idStr); NSLog(@"name=%@",name); NSLog(@"length=%@",length); NSLog(@"image=%@",image); NSLog(@"url=%@",url); } }]; }
NSXMLParser:
NSXMLParser采取的是SAX方式解析,特點是事件驅動,下面情況都會通知代理:
(1)當掃描到文檔(Document)的開始與結束
(2)當掃描到元素(Element)的開始與結束
一:使用步驟:
1、傳入XML數據,創建解析器
NSXMLParser *parser = [[NSXMLParseralloc] initWithData:data];
2、設置代理,監聽解析過程
parser.delegate =self;
3、開始解析
[parserparse];
二:NSXMLParserDelegate常用代理方法:
當掃描到文檔的開始時調用(開始解析)
- (void)parserDidStartDocument:(NSXMLParser *)parser
當掃描到文檔的結束時調用(解析完畢)
- (void)parserDidEndDocument:(NSXMLParser *)parser
當掃描到元素的開始時調用(attributeDict存放著元素的屬性)
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
當掃描到元素的結束時調用
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
#import "ViewController.h" @interface ViewController ()解析輸入結果:@end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ NSURL *url = [NSURL URLWithString:@"http://localhost:8080/myService/video?type=XML"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) { //1、傳入xml,創建解析器 NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data]; //2、設置代理、監聽解析過程 parser.delegate = self; //3、開始解析 [parser parse]; }]; } #pragma mark NSXMLParserDelegate代理方法 //當掃描到元素的開始時調用(attributeDict存放著元素的屬性) -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{ NSLog(@"===========%@元素開始解析========",elementName); if ([@"videos" isEqualToString:elementName]) { NSLog(@"%@是根節點",elementName); return; } NSString *idStr = attributeDict[@"id"]; NSString *name = attributeDict[@"name"]; NSString *length = attributeDict[@"length"]; NSString *image = attributeDict[@"image"]; NSString *urlStr = attributeDict[@"url"]; NSLog(@" \n id=%@ \n name=%@\n length=%@ \n image=%@ \n url=%@",idStr,name,length,image,urlStr); }; //當掃描到元素的結束時調用 -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{ NSLog(@"===========%@元素解析結束========",elementName); } //當掃描到文檔的開始時調用(開始解析) -(void)parserDidStartDocument:(NSXMLParser *)parser{ NSLog(@"parserDidStartDocument=====開始解析======="); } //當掃描到文檔的結束時調用(解析完畢) -(void)parserDidEndDocument:(NSXMLParser *)parser{ NSLog(@"parserDidEndDocument=====解析完畢========"); } @end