解析:從事先規定好的格式中提取數據
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,選擇添加
(2)在工程的Build Settings設置里面搜索search,找到Search paths選項下的Header Search Paths,加入一條/usr/include/libxml2這里三個反斜杠不能少
(3)在工程的Build Settings設置里面搜索Other Linker Flags,找到Other Linker Flags,雙擊空白處輸入-lxml2
這樣在編譯就不會報錯啦。??
//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);
}