05、網絡解析

解析:從事先規定好的格式中提取數據
iOS開發常見的解析:XML解析,JSON解析

XML解析

XMl事例:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 根結點 是所有節點的父節點或者爺節點 -->
<students> <!--開始節點-->
<!--student的子節點,position就是該節點的屬性-->
   <student position="憤青">
     <!--lyj是name節點的內容,我們可以將該節點所有的特性都用屬性來表示,但是為了閱讀起來方便,我們一般也會將該節點的特性用他的子節點來表示-->
     <name>lyj</name>
     <age>25</age>
     <sex>男</sex>
   </student>
   <student>
     <name>zza</name>
     <age>22</age>
     <sex>保密</sex>
   </student>
</students> <!--結束節點-->

XML有兩種解析方法:DOM(Document Object Model)解析和SAX(Simple API for XML)工具

1.SAX解析

SAX基本原理:采用事件驅動解析XML文件,以流式方式逐行的去讀,它不需要解析完整個文檔,在按內容順序解析文檔的過各中,SAX會判斷當前講到的字符是否合法XML語法中的某部分,如果符合就觸發事件(例如startDocument()、endDocument()諸如此類的事件),它的特點是不會記錄前面所碰到的標簽,并且它是一個解析速度快并且占用內存少的XML解析器
特點:
一.是基于事件驅動的解析方式
二.逐行解析
三.只能讀取(DOM解析可讀可寫)
四.一般只用做文檔比較大的時候

//sax解析
-(void)saxPath{
    //sax解析:基于事件驅動的解析方式,逐行解析
    NSString* xmlPath=[[NSBundle mainBundle] pathForResource:@"xml" ofType:@"xml"];
    NSString* xmlStr=[NSString stringWithContentsOfFile:xmlPath encoding:NSUTF8StringEncoding error:nil];
    //字符串轉data類型
    NSData* xmlData=[xmlStr dataUsingEncoding:NSUTF8StringEncoding];
    //參數:需要解析的文件內容
    NSXMLParser* xmlParser=[[NSXMLParser alloc] initWithData:xmlData];
    //設置代理
    xmlParser.delegate=self;
    //開始解析  同步的過程  當整個解析完成了才會執行下一行代碼
    BOOL isSuccess=[xmlParser parse];
    if (isSuccess) {
        NSLog(@"解析成功");
    }else{
        NSLog(@"解析失敗");
    }
    //解析的過程不結束,就不會執行該打印
    NSLog(@"我在解析的最底下");
  
}

下來遵循協議,實現協議方法,為了方便獲取數據,聲明一個字典和數組

@interface ViewController ()<NSXMLParserDelegate>
@property(nonatomic,strong)NSMutableArray* allDataArray;//存放所有student的節點
@property(nonatomic,strong)NSMutableDictionary* studentDic;//將student轉換為字典
@property(nonatomic,strong)NSString* noteValueString;//存儲節點中的值
#pragma mark--------parser解析的代理方法
//開始解析整個文檔了
-(void)parserDidStartDocument:(NSXMLParser *)parser{
        NSLog(@"開始解析整個文檔了");
    //初始化外部的可變數組,準備存放student節點
    self.allDataArray=[[NSMutableArray alloc] init]; 
    }
//當碰到開始節點或開始標簽的時候會執行的代理方法
//elementName:標簽名稱(節點名),例如<name>
//namespaceURI:命名空間的標識名 例如<teacher xmlns:l="www.lanou3g.com">
//qName:命名空間的值,就是上面的 www.lanou3g.com
//attributeDict:標簽的屬性 例如 <student position="憤青"> position就是標簽的屬性,attributeDict=={pasition:"憤青"}
-(void)parser:(NSXMLParser*)parser didStartElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName attributes:(nonnull NSDictionary<NSString *,NSString *> *)attributeDict{
    NSLog(@"碰到開始標簽----%@",elementName);
    //當開始解析student節點的時候,說明我們要用到字典了,就需要對字典進行初始化
    if ([elementName isEqualToString:@"student"]) {
        self.studentDic=[[NSMutableDictionary alloc] init];
    }
    
}
    
//取出標簽中的值
//string:就是標簽中的值
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
    NSLog(@"正在解析的值為---%@",string);
    //將節點的內容存儲起來,以供節點解析結束使用
    self.noteValueString=string;
    
}
    
//遇到當前正在解析標簽結束標簽
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
    NSLog(@"碰到結束標簽----%@",elementName);
    if ([elementName isEqualToString:@"name"]) {
        //說明name標簽解析結束
        [self.studentDic setObject:self.noteValueString forKey:elementName];
    }
    
    if ([elementName isEqualToString:@"age"]) {
        //說明age標簽解析結束
        [self.studentDic setObject:self.noteValueString forKey:elementName];
    }
    if ([elementName isEqualToString:@"sex"]) {
        //說明sex標簽解析結束
        [self.studentDic setObject:self.noteValueString forKey:elementName];
    }
    if ([elementName isEqualToString:@"student"]) {
        //說明一個student已經解析完成,說明一個字典已經完整,應該將字典放入數組中了
        [self.allDataArray addObject:self.studentDic];
    }
}
    
//整個文檔解析結束
-(void)parserDidEndDocument:(NSXMLParser *)parser{
        NSLog(@"整個文檔解析結束");
    //當整個文檔解析結束,說明所有的數據我們已經拿到,可以正常使用了
    NSLog(@"----%@",self.allDataArray);
  }

//當解析出錯會調用的方法
-(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{
    NSLog(@"解析出現錯誤---%@",parseError.description);
}
    
2.DOM解析

dom解析基于文檔驅動的解析方式,DOM解析XML時,讀入整個XML文檔并構建一個駐留內存的樹結構(節點樹),通過遍歷樹結構可以檢索任意XML節點,讀取他的屬性和值,而且通常情況下,可以借助XPath,直接查詢XML節點


使用方法:
1.獲取GDataXMLNode.h/m文件,將GDataXMLNode.h/m文件添加到工程中
2.向工程中增加“libxml2.dylib”動態庫
具體做法 選中整個工程 在Build Phases的倒數第二個選項中點“+”號,搜索libxml2.dylib 并添加
3.在工程的“Build Settings”頁中找到“Header Search Path” 點擊添加 "/usr/include/libxml2"
4.導入“GDataXMLNode.h”文件到頭文件 如果工程能編譯通過,說明添加成功
注意:
(1)在工程的Build phases設置的Link Binary With Libraries里面點擊加號,搜索libxml2.tbd,選擇添加

11111.png

(2)在工程的Build Settings設置里面搜索search,找到Search paths選項下的Header Search Paths,加入一條/usr/include/libxml2這里三個反斜杠不能少

222.png

(3)在工程的Build Settings設置里面搜索Other Linker Flags,找到Other Linker Flags,雙擊空白處輸入-lxml2


3333.png

這樣在編譯就不會報錯啦。??

//dom解析  基于文檔驅動的解析方式
-(void)domParser{
    //需要獲取解析的源文件
    NSString* xmlPath=[[NSBundle mainBundle] pathForResource:@"xml" ofType:@"xml"];
    NSString* xmlStr=[NSString stringWithContentsOfFile:xmlPath encoding:NSUTF8StringEncoding error:nil];
    //字符串轉data類型
    NSData* xmlData=[xmlStr dataUsingEncoding:NSUTF8StringEncoding];
   //dom解析
    //step1:將源xml文件轉換成樹狀結構的文檔放在內存中,以供遍歷獲取每個節點
    GDataXMLDocument* xmlDoc=[[GDataXMLDocument alloc] initWithData:xmlData encoding:NSUTF8StringEncoding error:nil];
    //step2:獲取根節點 就相當于獲取到了students節點
    GDataXMLElement* rootElement=[xmlDoc rootElement];
    //step3:獲取我們需要的子節點
    //參數:我們需要獲取的標簽名
//    NSArray* studentArray=[rootElement elementsForName:@"student"];
    //初始化一個可變數組,準備存放所有的student轉換成的字典
    NSMutableArray* allStudentsArray=[[NSMutableArray alloc] init];
    
    //添加節點(向現有的文檔動態的增加一個student節點)
    //節點創建   <student></student>
    GDataXMLElement* studentElement = [GDataXMLElement elementWithName:@"student"];
    //將student節點加入到它的父節點中
//    [rootElement addChild:studentElement];
    //為student增加子節點
    GDataXMLElement* nameElement = [GDataXMLElement elementWithName:@"name" stringValue:@"ze an"];
    GDataXMLElement* ageElement = [GDataXMLElement elementWithName:@"age" stringValue:@"23"];
    GDataXMLElement* genderElement = [GDataXMLElement elementWithName:@"gender" stringValue:@"未知"];
    [studentElement addChild:nameElement];
    [studentElement addChild:ageElement];
    [studentElement addChild:genderElement];
     [rootElement addChild:studentElement];
     NSArray* studentArray=[rootElement elementsForName:@"student"];
   

    
    //step4:遍歷數組
    //stuNode:對應一個student節點
/*<student>
    <name></name>
    <age></age>
    <sex></sex>
</student>
    */
    
    //每執行一次循環體,就相當于獲取了一個完整的student節點,結構如上
//    for (GDataXMLElement* stuelement in studentArray) {
//        //初始化一個字典
//      NSMutableDictionary* studentDic=[[NSMutableDictionary alloc] init];
////        NSString* name=[[[stuelement elementsForName:@"name"] firstObject] stringValue];
//        //獲取name節點
//        GDataXMLElement* nameElement=[stuelement elementsForName:@"name"].firstObject;
//        //取出節點中的值
//        NSString* name=[nameElement stringValue];
//        //將name的值放入字典中
//        [studentDic setObject:name forKey:@"name"];
//        
//        //獲取age節點
//        GDataXMLElement* ageElement=[stuelement elementsForName:@"age"].firstObject;
//        NSString* age=[ageElement stringValue];
//        [studentDic setObject:age forKey:@"age"];
//        
//        //獲取sex節點
//        GDataXMLElement* sexElement=[stuelement elementsForName:@"sex"].firstObject;
//        NSString* sex=[sexElement stringValue];
//        [studentDic setObject:sex forKey:@"sex"];
//        //將字典放入數組中
//        [allStudentsArray addObject:studentDic];
//    }
//    NSLog(@"----%@",allStudentsArray);
    
   
    for (GDataXMLElement* studentNode in studentArray) {
        //遍歷獲取student所有的子節點
        NSArray* subStudentNode=[studentNode children];
         NSMutableDictionary* studentDic=[[NSMutableDictionary alloc] init];
        for (GDataXMLElement* subOfStudentNode in subStudentNode) {
            //獲取子節點的名稱
            NSString* noteName=[subOfStudentNode name];
            //獲取節點內容
            NSString* noteValue=[subOfStudentNode stringValue];
            [studentDic setObject:noteValue forKey:noteName];
           
        }
        //  將字典加入到數組中
         [allStudentsArray addObject:studentDic];
    }
    NSLog(@"----%@",allStudentsArray);
    
    
}
3.JSON解析
//json解析
-(void)jsonParser{
    //獲取要解析的json源文件
    NSString* jsonPath=[[NSBundle mainBundle] pathForResource:@"DemoJson" ofType:@"json"];
    NSString* jsonStr=[NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil];
    //字符串轉data類型
    NSData* jsonData=[jsonStr dataUsingEncoding:NSUTF8StringEncoding];
    //json解析
   NSDictionary* dic= [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:nil];
    NSLog(@"---%@",dic);
    
}
    
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容