XML文件寫法
<Classes>//根節(jié)點
<Class1>//開始標簽
<Students>
<Student position = "CEO">//"CEO"節(jié)點屬性
//節(jié)點屬性
<name>hmx</name>
<age>23</age>
<height>160</height>
<Student>
<name>xiaoming</name>
<age>24</age>
<height>170</height>
</Student>
</Students>
</Class1>
</Classes>
XML解析
SAX:逐行解析(主類:NSXMLParser)
逐行解析顧名思義就是一行一行的讀取解析,需要遵循代理<NSXMLParserDelegate>
SAX一般分為5步
1.開始解析
- (void)parserDidStartDocument:(NSXMLParser *)parser;
2.開始解析標簽
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict;
3.標簽對應的值
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string;
4.結束解析標簽
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName;
5.結束解析
- (void)parserDidEndDocument:(NSXMLParser *)parser;
以上面的Student為例子
1.創(chuàng)建一個Student的model類
//Student的model類h文件
#import <Foundation/Foundation.h>
@interface Student : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, assign) float height;
@end
2.定義一個全局變量數組用來存儲解析后的數據,定義一個全局變量用來存儲標簽,因為我們要通過標簽來判斷數據
@property (nonatomic, strong) NSMutableArray *studentArray;
@property (nonatomic, strong) NSString *currentElementName;
3.這里使用一個UIbutton動作來進行解析,點擊button就進行XML解析,UIButton創(chuàng)建不在多說
//點擊按鈕進行解析
- (IBAction)SAXDidTapAction:(UIButton *)sender {
//獲取文件絕對路徑
NSString *path = [[NSBundle mainBundle] pathForResource:@"student" ofType:@"txt"];
//創(chuàng)建一個NSData
NSData *data = [NSData dataWithContentsOfFile:path];
//初始化XMLParser
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:data];
xmlParser.delegate = self;
[xmlParser parse];
}
4.遵循協議,重寫方法,記得數組需要先初始化
//開始解析
- (void)parserDidStartDocument:(NSXMLParser *)parser {
NSLog(@"DidStart");
}
//解析開始元素(標簽)
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict {
//記錄當前elementName
self.currentElementName = elementName;
//創(chuàng)建學生屬性并添加到數組中
if ([elementName isEqualToString:@"Student"]) {
Student *student = [[Student alloc] init];
[self.studentArray addObject:student];
}
}
//每一個標簽對應的值
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
//獲取最后一個元素
Student *stu = [self.studentArray lastObject];
//KVC模式賦值,記得在Student類中重寫方法
//- (void)setValue:(id)value forUndefinedKey:(NSString *)key;
[stu setValue:string forKey:self.currentElementName];
}
//解析結束標簽
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
//這里設置為空的原因: foundCharacters方法在結束標簽處會調用一次,
//不置為空會再次進入KVC賦值,Student內容會變?yōu)榭栈?
self.currentElementName = @"";
}
//結束解析
- (void)parserDidEndDocument:(NSXMLParser *)parser {
NSLog(@"DidEnd");
for (Student *stu in self.studentArray) {
NSLog(@"%@", stu);
}
}
DOM解析:通過GDataXMLNode類進行解析,該類會將數據全部解析完畢,在使用前先做一些處理
1.將文件添加到工程(http://pan.baidu.com/s/1eSrvPgY)
2.在工程中添加動態(tài)庫: libxml2.dylib
3.在工程的Build Settings中找到Header Search Path項 添加/usr/include/libxml2
4.將第三方庫文件改為ARC MRC通用狀態(tài),找到Build Phases中的Compile Sources中的GDataXMLNode.m文件雙擊添加-fno-objc-arc
程序
- 初始化GDataXMLDocument
//data為路徑,解析例子同SAX, data為SAX中的data
GDataXMLDocument *GDocument = [[GDataXMLDocument alloc] initWithData:data options:0 error:&error];
- 獲取根節(jié)點
GDataXMLElement *rootElement = GDocument.rootElement;
- 獲取子節(jié)點
for (GDataXMLElement *subElement in rootElement.children) {
Student *stu = [[Student alloc] init];
//找到student的子節(jié)點, 也就是name age height,然后賦值
for (GDataXMLElement *contactElement in subElement.children) {
[stu setValue:contactElement.stringValue forKey:contactElement.name];
}
[self.studentArray addObject:stu];
}
通過XMLDictionary類進行解析
NSDictionary *dict = [NSDictionary dictionaryWithXMLData:data];
NSArray *array = dict[@"Student"];
for (NSDictionary *stuDict in array) {
Student *stu = [[Student alloc] init];
[stu setValuesForKeysWithDictionary:stuDict];
[self.studentArray addObject:stu];
}
上面的均為簡單的例子,下面來看一個比較復雜的例子,這里使用XMLDictionary類進行解析: Cartoon.xml進行解析
這里我們只需要兩個數據,name跟desc
- 創(chuàng)建Model類
Model.h
@interface CartoonModel : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *desc;
@end
Model.m
#import "CartoonModel.h"
@implementation CartoonModel
//當沒有找到key時會進入這個方法
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
}
@end
- 數據解析
//這里使用懶加載方法,cartoonArray為全局變量(NSMutableArray)
- (NSMutableArray *)cartoonArray {
if (!_cartoonArray) {
_cartoonArray = [[NSMutableArray alloc] init];
//獲取絕對路徑
NSString *path = [[NSBundle mainBundle] pathForResource:@"Cartoon" ofType:@"xml"];
NSData *data = [NSData dataWithContentsOfFile:path];
//使用方法dictionaryWithXMLData將數據轉換為字典
NSDictionary *dict = [NSDictionary dictionaryWithXMLData:data];
//通過字典的key獲取下級字典
NSDictionary *resultDict = dict[@"results"];
//通過數組接收數據
NSArray *albumInfoDict = resultDict[@"AlbumInfo"];
//通過model類接收數組內部的各個model數據
for (NSDictionary *modelDict in albumInfoDict) {
CartoonModel *model = [[CartoonModel alloc] init];
//KVC模式賦值
[model setValuesForKeysWithDictionary:modelDict];
[_cartoonArray addObject:model];
}
}
return _cartoonArray;
}