解析方式
- DOM MAC提供的解析方法 (Document Object Model ,文檔對(duì)象模型入偷。解析時(shí)需要將XML文件整體讀入哗魂,并且將XML結(jié)構(gòu)化成樹狀,使用時(shí)再通過樹狀結(jié)構(gòu)讀取相關(guān)數(shù)據(jù)焚志,查找特定節(jié)點(diǎn),然后對(duì)節(jié)點(diǎn)進(jìn)行讀或?qū)?iOS中無法直接使用
- 原因:內(nèi)存開銷巨大!
- 可讀可寫
- 將數(shù)據(jù)已樹形結(jié)構(gòu)加載到內(nèi)存
- SAX iOS提供的解析方式 (Simple API for XML畏鼓,基于事件驅(qū)動(dòng)的解析方式酱酬,逐行解析數(shù)據(jù),采用協(xié)議回調(diào)機(jī)制)
- 內(nèi)存開銷小
- 只讀
- 速度快
- 從上到下,順序解析的過程
解析思路
- 打開文檔(準(zhǔn)備)
- 開始節(jié)點(diǎn)
- 發(fā)現(xiàn)節(jié)點(diǎn)內(nèi)容(一個(gè)節(jié)點(diǎn)內(nèi)容,可能會(huì)讀取很多次!)(內(nèi)容是節(jié)點(diǎn)回到2)
- 結(jié)束節(jié)點(diǎn)
- 文檔解析完成!
解析方法
NSXMLParse:開發(fā)用這個(gè)官方
蘋果原生云矫,SAX方式解析膳沽,它基于事件通知的模式,一邊讀取文檔一邊解析數(shù)據(jù)让禀,不用等待文檔全部讀入以后再解析挑社,所以如果你正打印解析的數(shù)據(jù),而解析過程中間出現(xiàn)了錯(cuò)誤巡揍,那么在錯(cuò)誤節(jié)點(diǎn)之間的數(shù)據(jù)會(huì)正常打印痛阻,錯(cuò)誤后面的數(shù)據(jù)不會(huì)被打印。解析過程由NSXMLParserDelegate協(xié)議方法回調(diào)腮敌。
第三方框架
libxml2:純C語言框架阱当,默認(rèn)包含在iOS SDK,同時(shí)支持DOM 和SAX解析
GDataXMl:谷歌開發(fā) ,基于libxml2糜工,支持DOM解析
思維導(dǎo)圖
解析代碼
//1.可變數(shù)組
@property(nonatomic,strong)NSMutableArray *videos;
//2.當(dāng)前解析的節(jié)點(diǎn)模型
@property(nonatomic,strong)Video *currentVideo;
//3.拼接字符串--可變字符串
@property(nonatomic,strong)NSMutableString *elementStr;
@end
@implementation ViewController
-(NSMutableArray *)videos
{
if (!_videos) {
_videos = [[NSMutableArray alloc]init];
}
return _videos;
}
-(NSMutableString *)elementStr
{
if (!_elementStr) {
_elementStr = [[NSMutableString alloc]init];
}
return _elementStr;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self loadData];
}
//MARK -- XML解析
- (void)loadData {
//1.url
NSURL *url = [NSURL URLWithString:@"http://localhost:8080/videos.xml"];
//2.request
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:1 timeoutInterval:10.0];
//3.發(fā)現(xiàn)請(qǐng)求
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
// //XML解析 是一個(gè)耗時(shí)操作弊添!
// NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data];
//
// //設(shè)置代理 -旦解析器開始解析,后續(xù)的工作就會(huì)由代理來監(jiān)聽
// parser.delegate = self;
//
//
// //解析器解析
// [parser parse];
NSXMLParser* paraser = [[NSXMLParser alloc] initWithData:data];
paraser.delegate = self;
[paraser parse];
}];
}
#pragma mark --<XML解析代理方法>
//1.打開文檔
-(void)parserDidStartDocument:(NSXMLParser *)parser
{
NSLog(@"1.開始文檔");
//1.清空數(shù)組
[self.videos removeAllObjects];
}
//2.開始節(jié)點(diǎn)
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict
{
//elementName 節(jié)點(diǎn)名稱
//namespaceURI 命名空間
//qualifiedName 命名空間限定的本地名稱
//attributes 屬性
NSLog(@"2.開始節(jié)點(diǎn) %@ %@",elementName,attributeDict);
if ([elementName isEqualToString:@"video"]) {
//1.新建模型
self.currentVideo = [[Video alloc]init];
//2設(shè)置videoID的屬性
self.currentVideo.videoId = @([attributeDict[@"videoId"]intValue]);
}
}
//3.發(fā)現(xiàn)節(jié)點(diǎn)內(nèi)容
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
//拼接字符串
NSLog(@"==> %@",string);
[self.elementStr appendString:string];
}
//4.結(jié)束節(jié)點(diǎn)
/*
kvc
*/
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
NSLog(@"4.結(jié)束節(jié)點(diǎn):%@",elementName);
if ([elementName isEqualToString:@"video"]) {
[self.videos addObject:self.currentVideo];
}else if (![elementName isEqualToString:@"videos"])
{
[self.currentVideo setValue:self.elementStr forKey:elementName];
}
//清空字符串
[self.elementStr setString:@""];
}
//5.結(jié)束解析
-(void)parserDidEndDocument:(NSXMLParser *)parser
{
NSLog(@"5.結(jié)束解析捌木!%@",self.videos);
}
//6.出現(xiàn)錯(cuò)誤(主要是網(wǎng)絡(luò)開發(fā)表箭,就需要對(duì)出錯(cuò)進(jìn)行處理)
-(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
NSLog(@"發(fā)生錯(cuò)誤");
}