NSXMLParser是iOS自带SAX方式解析,使用方法为:
1.// 传入XML数据,初始化解析器
[[NSXMLParser alloc] initWithContentsOfURL:url];
2.// 设置代理,监听解析过程
3.parser.delegate = self;
// 开始解析
[parser parse];
这样就开始解析了,解析过程通过NSXMLParserDelegate来完成,主要方法有
/**
开始解析文档
*/
- (void)parserDidStartDocument:(NSXMLParser *)parser
2
/**
开始解析节点
@param elementName 节点名称
@param attributeDict 节点属性
*/
- (void)parser:(NSXMLParser *)parser didStartElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName attributes:(nonnull NSDictionary<NSString *,NSString *> *)attributeDict
3
/**
一个节点解析完毕
@param elementName 节点名称
*/
- (void)parser:(NSXMLParser *)parser didEndElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName
/**
解析文本,会多次解析,每次只解析1000个字符,如果多月1000个就会多次进入这个方法
*/
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
/**
文档解析结束
*/
- (void)parserDidEndDocument:(NSXMLParser *)parser
一般解析单层xml文件都很简单,这里不做介绍,主要是解析多层xml文件,并且多层xml文件中还有重复名称的节点
下面是我做的一个demo,代码如下
xml文件如下
<Persons>
<Person>
<name>张三</name>
<age>23</age>
<sex>男</sex>
</Person>
<Person>
<name>李四</name>
<age>30</age>
<sex>男</sex>
<Students>
<Student>
<name>小明</name>
<age>10</age>
<sex>男</sex>
</Student>
<Student>
<name>小红</name>
<age>12</age>
<sex>女</sex>
</Student>
</Students>
</Person>
<Person>
<name>王五</name>
<age>20</age>
<sex>女</sex>
</Person>
</Persons>
根据xml文件,我定义了两个模型,一个p
Person,一个Student,模型代码如下
Person
.h
#import <Foundation/Foundation.h>
#import "Student.h"
NS_ASSUME_NONNULL_BEGIN
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, copy) NSString *sex;
@property (nonatomic, strong) NSArray <Student *>*students;
@end
NS_ASSUME_NONNULL_END
///////////////////////////////////////////////////////////////
.m
#import "Person.h"
@implementation Person
- (NSString *)description{
NSMutableString *str = [NSMutableString string];
if (self.students.count) {
for (Student *student in self.students) {
[str appendFormat:@"%@\n",student.description];
}
}
return [NSString stringWithFormat:@"\n姓名:%@\n年龄:%ld\n性别:%@\n学生:\n%@",self.name,self.age,self.sex,str];
}
@end
Student
.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface Student : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, copy) NSString *sex;
@end
NS_ASSUME_NONNULL_END
////////////////////////////////////////////////////////////
.m
#import "Student.h"
@implementation Student
- (NSString *)description{
return [NSString stringWithFormat:@"姓名:%@ 年龄:%ld 性别:%@",self.name,self.age,self.sex];
}
@end
解析代码
#import "ViewController.h"
#import "Person.h"
#import "Student.h"
@interface ViewController ()<NSXMLParserDelegate>
@property (nonatomic, strong) NSMutableArray <Person *> *persons;
@property (nonatomic, strong) NSMutableArray <Student *> *students;
@property (nonatomic, strong) Person *person;
@property (nonatomic, strong) Student *student;
@property (nonatomic, strong) NSMutableString *currentString;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"Person.xml" ofType:nil]];
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
parser.delegate = self;
[parser parse];
}
#pragma mark -- NSXMLParserDelegate
/**
文档解析结束
*/
- (void)parserDidEndDocument:(NSXMLParser *)parser{
for (Person *person in self.persons) {
NSLog(@"%@",person);
}
}
/**
开始解析节点
@param elementName 节点名称
@param attributeDict 节点属性
*/
- (void)parser:(NSXMLParser *)parser didStartElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName attributes:(nonnull NSDictionary<NSString *,NSString *> *)attributeDict{
if ([elementName isEqualToString:@"Persons"]){
self.persons = [NSMutableArray array];
}else if ([elementName isEqualToString:@"Students"]){
self.students = [NSMutableArray array];
}else if ([elementName isEqualToString:@"Person"]) {
self.person = [[Person alloc] init];
}else if ([elementName isEqualToString:@"Student"]){
self.student = [[Student alloc] init];
}
self.currentString = [NSMutableString string];
}
/**
一个节点解析完毕
@param elementName 节点名称
*/
- (void)parser:(NSXMLParser *)parser didEndElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName{
if ([elementName isEqualToString:@"name"]) {
if(self.student){
self.student.name = self.currentString;
}else{
self.person.name = self.currentString;
}
}else if ([elementName isEqualToString:@"age"]){
if (self.student) {
self.student.age = [self.currentString integerValue];
}else{
self.person.age = [self.currentString integerValue];
}
}else if ([elementName isEqualToString:@"sex"]){
if (self.student) {
self.student.sex = self.currentString;
}else{
self.person.sex = self.currentString;
}
}else if ([elementName isEqualToString:@"Person"]){
Person *person = self.person;
[self.persons addObject:person];
self.person = nil;
}else if ([elementName isEqualToString:@"Student"]){
Student *student = self.student;
[self.students addObject:student];
self.student = nil;
}else if ([elementName isEqualToString:@"Students"]){
NSArray *students = [self.students copy];
self.person.students = students;
}
}
/**
解析文本,会多次解析,每次只解析1000个字符,如果多月1000个就会多次进入这个方法
*/
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
[self.currentString appendString:string];
}
@end
解析完成打印结果
2019-07-10 15:54:52.291541+0800 RN-iOS-Demo[48953:10658087]
姓名:张三
年龄:23
性别:男
学生:
2019-07-10 15:54:52.291739+0800 RN-iOS-Demo[48953:10658087]
姓名:李四
年龄:30
性别:男
学生:
姓名:小明 年龄:10 性别:男
姓名:小红 年龄:12 性别:女
2019-07-10 15:54:52.291814+0800 RN-iOS-Demo[48953:10658087]
姓名:王五
年龄:20
性别:女
学生:
网友评论