1. 程式人生 > >iOS ——XML資料結構及其兩種解析資料的方式SAX 、DOM

iOS ——XML資料結構及其兩種解析資料的方式SAX 、DOM

1.解析的基本概念
所謂解析:從事先規定好的格式中提取資料
解析的前提:提前規定好格式、資料提供方按照格式提供資料、資料獲取方則按照格式獲取資料。
iOS 常見的解析:XML 解析、JSON 解析

2.XML 基本概念
XML:Extensible Markup language(可擴充套件標記語⾔言)主流資料格式之 一,可以用來儲存和傳輸資料。
XML 資料格式的功能:資料交換、記憶體管理、用作配置檔案。
XML 資料結構的語法
宣告:
節點使用一對標籤標示。其實結束標籤。
根節點是起始節點,只有一個。節點可以巢狀。
節點可以有值。儲存在一對標籤中。

這裡寫圖片描述
這裡寫圖片描述

3.SAX 解析


1)SAX :Simple API for XML。基於事件驅動的解析⽅方式,逐⾏行解析 資料。(採⽤用協議回撥機制)
2)NSXMLParser是iOS⾃自帶的XML解析類。採⽤用SAX⽅方式解析資料。
3)解析過程由NSXMLParserDelegate協議⽅方法回撥
4)解析過程:開始標籤->取值->結束標籤->取值
程式碼如下:
StudentInfor_XML.txt 檔案

<students>  //根節點 開始標籤
<student>   //根節點的子節點, name 的父節點
<name>懶洋洋</name
>
//懶洋洋 :節點的值 <age>3</age> <gender>male</gender> <hobby></hobby> <phone>128395069078</phone> </student> <student> <name>懶洋洋1</name> <age>3</age> <gender>male</gender> <hobby></hobby> <phone>128395069078</phone
>
</student> <student> <name>懶洋洋2</name> <age>3</age> <gender>male</gender> <hobby></hobby> <phone>128395069078</phone> </student> </students> //節點的結束標籤

XML解析步驟:
1、例項化NSXMLParser,傳入從伺服器接收的XML資料
2、定義解析器代理
3、解析器解析,通過解析代理方法完成XML資料的解析。
解析XML用到的的代理方法:
1. 開始解析XML文件
- (void)parserDidStartDocument:
2. 開始解析某個元素,會遍歷整個XML,識別元素節點名稱,如開頭
-(void)parser:didStartElement:namespaceURI:qualifiedName:attributes:
3. 文字節點,得到文字節點裡儲存的資訊資料。 節點中的資料XXXX
- (void)parser:foundCharacters:
4. 結束某個節點 如開頭
- (void)parser:didEndElement:namespaceURI:qualifiedName:

注意:在解析過程中,2、3、4三個方法會不停的重複執行,直到遍歷完成為止
5.解析XML文件結束
- (void)parserDidEndDocument:
6.解析出錯
-(void)parser:parseErrorOccurred:

//存放model 物件的容器
@property (nonatomic, strong) NSMutableArray * array;
//當前節點
@property (nonatomic, strong) NSString * currentElement;


 #pragma mark XMLBUtton 的點選事件
 - (IBAction)xmlSAXAction:(id)sender {
 //  1. 獲取檔案路徑
 NSString * path = [[NSBundle mainBundle]pathForResource:@"StudentInfor_XML" ofType:@"txt"];
 //    2.根據檔案物件建立data 物件 (使用init 方法)
 NSData * data = [[NSData alloc] initWithContentsOfFile:path];
 //    3. 根據data 物件建立解析物件
 NSXMLParser * xmlparser = [[NSXMLParser alloc] initWithData:data];
 //    4. 設定代理
 xmlparser.delegate = self;
 //  5.開始解析 方法 - (BOOL)parse;
 [xmlparser parse];
 }

#pragma mark -  SAX 解析        SAX代理步驟---
#pragma mark - 1.開始文件解析
-(void)parserDidStartDocument:(NSXMLParser *)parser
{
//    開始文件解析的時候準備陣列
//    數組裡面存的是指標。
//    initWithCapacity 方法初始化 : 6 的倍數初始化。 剛開始6個。 放到7個的時候,12。13時候24。25的時候48. 減少陣列在記憶體中的遷移。
    _array = [[NSMutableArray alloc] initWithCapacity:6];
}

#pragma mark 2. 開始標籤解析
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
//    記錄當前標籤
    _currentElement = elementName;
//    根據標籤student 建立model
    if ([elementName isEqualToString: @"student"]) {
//        此時新增到陣列中的 student物件為空。解析出來時再新增物件的值
        Student * student = [Student new];
        [_array addObject:student];
    }
}
#pragma mark 3.獲取標籤內容
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    //獲取陣列最後一個元素 (獲取陣列中的隨後一個元素,給最後一個元素賦值。如果是第一個元素賦值,會覆蓋)
    Student * student = [_array lastObject];
//    KVC 賦值
    [student setValue:string forKey:_currentElement];
}

#pragma mark - 4. 結束標籤解析
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    NSLog(@"結束標籤解析");
//    當前儲存點置為空, 不影響下次判斷
    _currentElement = nil; 
}
#pragma mark 5.結束文件解析
-(void)parserDidEndDocument:(NSXMLParser *)parser
{
    NSLog(@"結束文件解析");
//    檢驗資料
    for (Student * student  in _array) {
        NSLog(@"%@",student);
        }
    }
#pragma mark 6. 錯誤處理
-(void) parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
    NSLog(@"寫錯了,錯誤為%@",parseError);
}

總結:先開始文件解析,再開始標籤解析。解析標籤時,一個student 標籤需要全部解析完在解析下一個,所以需要每次取出陣列中Student * student = [_array lastObject]; 賦上解析的資料。

4.使用DOM 工具解析XML
DOM 解析
1)DOM:Document Object Model(⽂文件物件模型)。解析時需要
將XML⽂檔案整體讀⼊入,並重點內容且將XML結構化成樹狀,使⽤用時再通過樹 狀結構讀取相關資料
2)GDataXMLNode是Google提供的開源XML解析類,對
libxml2.dylib進⾏行了Objective-C的封裝
程式碼:

#pragma mark - XML DOM 解析 --

 - (IBAction)xmlDOMAction:(id)sender
 {
 //    1. 獲取檔案路徑
 //    獲取應用程式包
 NSBundle * bundle = [NSBundle mainBundle];
 //    通過包獲取路徑
 NSString * path = [bundle pathForResource:@"StudentInfor_XML" ofType:@"txt"];
 //    2. 根據檔案路徑獲取data 物件 (使用遍歷構造器方法)
 NSData * data = [NSData dataWithContentsOfFile:path];
 //    3. 根據datda 物件建立解析物件
 GDataXMLDocument * document = [[GDataXMLDocument alloc] initWithData:data options:0 error:nil];
 //    4.獲取根節點 (本題中<students>)
 GDataXMLElement * rootElement = [document rootElement];
 //   初始化陣列,開闢空間(開闢6個指標大小的空間,給array)
 _array = [[NSMutableArray alloc]initWithCapacity:6];
// 遍歷根節點的孩子節點 ,獲取每個孩子節點(<student>) 
for (GDataXMLElement * subEement in rootElement.children) {
 //建立物件
 Student * student = [Student new];
 for (GDataXMLElement * element in subEement.children) {
//遍歷 孩子節點的孩子節點,獲取每個孩子節點的值。並給student 的各個屬性賦值。
 [student setValue:element.stringValue forKey:element.name];
 }
 //        新增到陣列中
 [_array addObject:student];
 }
 //    校驗
 for (Student * student  in _array) {
 NSLog(@"%@",student);
 }
 }

總結:iOS 中對XML 檔案的解析方法有兩種:DOM 、SAX
比較:
1.SAX方法可以使用iOS SDK中的NSXMLParser,DOM方法可以使用GOOGLE提供的GDataXML。
2、SAX(SimpleAPI for XML)
只能讀,不能修改,只能順序訪問,適合解析大型XML,解析速度快
常應用於處理大量資料的XML,實現異構系統的資料訪問,實現跨平臺
從文件的開始通過每一節點移動,定位一個特定的節點
3、DOM(DocumentObject Model)
不僅能讀,還能修改,而且能夠實現隨機訪問,缺點是解析速度慢,適合解析小型文件.方便操作.
在記憶體中生成節點樹操作代價昂貴。

詳細理解:
DOM將整個xml看成是一個樹狀的結構,在解析的時候,會將整個xml檔案載入到我們的記憶體當中,然後通過DOM提供的API來對我們的xml資料進行解析,這種方式解析xml非常的方便,並且我們可以通過某個節點訪問到其兄弟或者是父類、子類節點。
不好的地方就是,其會將整個xml文件載入到記憶體中,這樣會大大的佔用我們的記憶體資源,對於手機來說,記憶體資源是非常非常寶貴的。
SAX相對於DOM 速度慢但是佔用記憶體小,非常適合用於移動裝置。 SAX解析XML檔案採用的是事件驅動,也就是說,它並不需要解析完整個文件,在按內容順序解析文件的過程中,SAX會判斷當前讀到的字元是否合法XML語法中的某部分,如果符合就會觸發事件。