ViewController.m
/*
解析XML文档的两种方式(Document Object Model(文档对象模型),Simple API for XML):
1.Sax 解析:使用系统提供的NSXMLParserDelegate进行解析
2.Dom 解析:DOM方式解析XML时,读入整个XML文档并构建一个驻留内存的树结构(节点树),通过遍历树结构可以检索任意XML节点,读取它的属性和值。而且通常情况下,可以借助XPath,直接查询XML节点。
*/
#import "ViewController.h"
#import "message.h"
@interface ViewController ()<NSXMLParserDelegate>
- (IBAction)saxForXML:(UIButton *)sender;
//解析时需要使用的数组:
@property(nonatomic,strong)NSMutableArray *dataArray;
//定义一个可变字符串,拼接使用
@property(nonatomic,strong)NSMutableString *appendString;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)saxForXML:(UIButton *)sender {
/*
SAX解析:
要解析的是什么数据
解析的数据用什么接收
谁有解析 XML 的能力
使用代理对象告知解析器什么时候开始解析
*/
//1.找到需要解析的数据
NSString *filePath = [[NSBundle mainBundle]pathForResource:@"message.txt" ofType:nil];
//2.将转换的文件转换为数据
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
//3.创建解析器对象,并给它需要解析的对象
NSXMLParser *parser = [[NSXMLParser alloc]initWithData:fileData];
//4.给解析器设置代理
parser.delegate = self;
//5.通知解析器干活
[parser parse];
}
//实现协议中的方法:
#pragma mark --- 4.1开始解析文档:
-(void)parserDidStartDocument:(NSXMLParser *)parser{
//解析出来的文档,数据需要存储,所以定义可变数组
self.dataArray = [NSMutableArray array];
}
#pragma mark --- 4.2.开始解析标签
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict{
NSLog(@"开始解析标签");
if ([elementName isEqualToString:@"message"]) {
//创建模型对象
message *mes = [message new];
//将模型放入数组中
[self.dataArray addObject:mes];
}
//初始化一个可变字符串,拼接使用
self.appendString = [NSMutableString string];
}
#pragma mark --- 4.3.获取文本
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
//在获取文本内容时,未必可以一次性取出,可能多次取出,所以需要拼接
NSLog(@"获取文本");
[self.appendString appendString:string];
}
#pragma mark --- 4.4.结束标签解析
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
NSLog(@"结束当前标签");
//找到数组最后一个元素,创建 model 对象
message *mes = [self.dataArray lastObject];
//使用 KVC, 通过 key 将拼接的字符串给 modle
[mes setValue:self.appendString forKey:elementName];
//拼接完毕,需要对字符串进行清空
self.appendString = nil;
}
#pragma mark --- 4.5.结束解析文档
-(void)parserDidEndDocument:(NSXMLParser *)parser
{
//将数组中存储的对象打印出来,进行测试
[self.dataArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"%@, %@, %@",[obj recevier],[obj content],[obj sender]);
}];
}
-(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{
NSLog(@"解析文档出错:%@",parseError);
}
@end
message.h
#import <Foundation/Foundation.h>
//model 中设置的属性,要和 xml 中的标签名字一样
@interface message : NSObject
@property(nonatomic,copy)NSString *recevier;
@property(nonatomic,copy)NSString *content;
@property(nonatomic,copy)NSString *sender;
@end
message.m
#import "message.h"
@implementation message
-(void)setValue:(id)value forUndefinedKey:(NSString *)key
{
}
@end
message.txt
<?xml version = "1.0" encoding = "UTF-8"?>
<messages>
<message>
<received>尼古拉斯.凯奇</received>
<content>不见不散</content>
<sender>王军</sender>
</message>
<message>
<received>王军</received>
<content>你媳妇来了</content>
<sender>尼古拉斯.凯奇</sender>
</message>
</messages>