在iPhone開發中,XML的解析有很多選擇,iOS SDK提供了NSXMLParser和libxml2兩個類庫,另外還有很多第三方類庫可選,例如TBXML、TouchXML、KissXML、TinyXML和GDataXML。問題是應該選擇哪一個呢?
解析 XML 通常有兩種方式,DOM 和 SAX:
DOM解析XML時,讀入整個XML文檔并建構一個駐留記憶體的樹結構(節點樹),通過周遊樹結構可以檢索任意XML節點,讀取它的屬性和值。而且通常情況下,可以借助XPath,直接查詢XML節點。
SAX解析XML,是基于事件通知的模式,一邊讀取XML文檔一邊處理,不必等整個文檔加載完之後才采取操作,當在讀取解析過程中遇到需要處理的對象,會發出通知對其進行處理。
一般在iOS平台下,比較常用的XML解析類庫有如下幾種:
如果是讀取很小的XML文檔,性能基本上沒有什麼差别,不過從調用的友善性來說,建議使用TouchXML、KissXML或GDataXML
如果是需要讀取和修改XML文檔,建議使用KissXML或GDataXML
如果需要讀取非常大的XML文檔,則建議使用libxml2或TBXML
如果你不想去調用第三方類庫,那麼使用NSXML也可以
安裝說明
GDataXML
2. 解壓縮檔案,找到Source\XMLSupport,并且将其中的GDataXMLNode.h 和 GDataXMLNode.m檔案拖到項目中
3. 選中項目,選中“Build Settings”标簽頁
4. 将Build Settings頁中,頂部的“Basic”标簽切換到“All”
5. 找到“Paths\Header Search Paths”項,并添加“/usr/include/libxml2”到清單中
6. 找到“Linking\Other Linker Flags”項,并添加“-lxml2”到清單中
在需要調用GDataXML的代碼檔案頭部,加入:
#import “GDataXMLNode.h”
TouchXML
2. 解壓後,将其中的Sources目錄下的檔案和目錄都拖到項目中
在需要調用TouchXML的代碼檔案頭部,加入:
#import “TouchXML.h”
TBXML
2. 解壓後,将其中的TBXML.h, TBXML.m, NSDataAdditions.h和NSDataAddtions.m四個檔案拖到項目中
3. 添加對libz.dylib類庫的應用
在需要調用TBXML的代碼檔案頭部,加入:
#import “TBXML.h”
使用說明
讀取XML檔案,并解析成為DOM文檔對象示例:
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"xml"];
NSData *xmlData = [[NSMutableData alloc] initWithContentsOfFile:filePath];
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
if (doc == nil) { return nil; }
NSLog(@"%@", doc.rootElement);
[doc release];
[xmlData release];
下面專門介紹谷歌的GdataXml,GdataXml是專門的谷歌解析XML的解析類。就是之前的設定複雜點。
GDataXml 相同标簽的多個屬性,好多文檔都沒有介紹擷取屬性的方法,讓我找的好苦啊,必須分享!!!
首先向Frameworks檔案中添加libxml2.dylib這個庫,而後再Croups & Files 側邊欄中輕按兩下我們的工程圖示,找到 build 修改兩個屬性如下:
在Search Paths中 找到Header Search Paths 将其對應的值修改為:/usr/includebxml2
在Linking中找到 Other Linker Flags 對應的值改為:-lxml2
GDataXMLDocument *doc=[[GDataXMLDocument alloc]initWithXMLString:resp*****eBody opti*****:2 error:nil];
if (doc!=nil) {
GDataXMLElement *root=[doc rootElement ];
NSLog(@"--------root's children:--------\n%@", root);
//取出根節點的所有孩子節點
//取出某一個具體節點(body節點)
[returnInfo setObject:[[[root elementsForName:@"db:uid"] objectAtIndex:0] stringValue] forKey:@"snsUserUid"];
[returnInfo setObject:[[[root elementsForName:@"title"]objectAtIndex:0]stringValue] forKey:@"snsNickName"];
[returnInfo setObject:[[[root elementsForName:@"db:location"]objectAtIndex:0]stringValue] forKey:@"snsProvince"];
[returnInfo setObject:[[[[root elementsForName:@"link"] objectAtIndex:2]attributeForName:@"href"] stringValue] forKey:@"snsProfileImageUrl"];
[returnInfo setObject:@"4" forKey:@"snsLandEntrance"];
NSLog(@"%@",[[[root elementsForName:@"link"] objectAtIndex:2]attributes]);
NSLog(@"%@",[[[root elementsForName:@"db:location"]objectAtIndex:0]stringValue]);
}
NSLog(@"returnInforeturnInforeturnInforeturnInforeturnInfo%@",returnInfo);
谷歌的GdataXML支援Xpath文法查詢
<?xml version="1.0" encoding="ISO-8859-1"?> <catalog> <cd country="USA"> <title>Empire Burlesque</title> <artist>Bob Dylan</artist> <price>10.90</price> </cd> <cd country="UK"> <title>Hide your heart</title> <artist>Bonnie Tyler</artist> <price>9.90</price> </cd> <cd country="USA"> <title>Greatest Hits</title> <artist>Dolly Parton</artist> <price>9.90</price> </cd> </catalog>
定位節點
XML是樹狀結構,類似檔案系統內資料夾的結構,XPath也類似檔案系統的路徑命名方式。不過XPath 是一種模式(Pattern),可以選出 XML檔案中,路徑符合某個模式的所有節點出來。例如要選catalog底下的cd中所有price元素可以用:
/catalog/cd/price
如果XPath的開頭是一個斜線(/)代表這是絕對路徑。如果開頭是兩個斜線(//)表示檔案中所有符合模式的元素都會被選出來,即使是處於樹中不同的層級也會被選出來。以下的語法會選出檔案中所有叫做cd的元素(在樹中的任何層級都會被選出來):
//cd
選擇未知的元素
使用星號(Wildcards,*)可以選擇未知的元素。下面這個語法會選出/catalog/cd 的所有子元素:
/catalog/cd/*
以下的語法會選出所有catalog的子元素中,包含有price作為子元素的元素。
/catalog/*/price
以下的語法會選出有兩層父節點,叫做price的所有元素。
/*/*/price
以下的語法會選擇出檔案中的所有元素。
//*
要注意的是,想要存取不分層級的元素,XPath語法必須以兩個斜線開頭(//),想要存取未知元素才用星號(*),星號隻能代表未知名稱的元素,不能代表未知層級的元素。
選擇分支
使用中括號可以選擇分支。以下的語法從catalog的子元素中取出第一個叫做cd的元素。XPath的定義中沒有第0元素這種東西。
/catalog/cd[1]
以下語法選擇catalog中的最後一個cd元素:(XPathj並沒有定義 first() 這種函式喔,用上例的 [1]就可以取出第一個元素。
/catalog/cd[last()]
以下語法選出含有price子元素的所有/catalog/cd元素。
/catalog/cd[price]
以下語法選出price元素的值等於10.90的所有/catalog/cd元素
/catalog/cd[price=10.90]
以下語法選出price元素的值等於10.90的所有/catalog/cd元素 的price元素
/catalog/cd[price=10.90]/price
選擇一個以上的路徑
使用Or運算元(|)就可以選擇一個以上的路徑。例如:
/catalog/cd/title | catalog/cd/artist
選擇所有title以及artist元素
//title | //artist
選擇所有title以及artist以及price元素
//title | //artist | //price
選擇屬性
在XPath中,除了選擇元素以外,也可以選擇屬性。屬性都是以@開頭。例如選擇檔案中所有叫做country的屬性:
//@country
選擇所有含有country這個屬性的cd元素:
//cd[@country]
以下語法選擇出含有屬性的所有cd元素
//cd[@*]
以下語法選擇出country屬性值為UK的cd元素
//cd[@country='UK']