XML解析
2016-01-11 22:45
309 查看
在iPhone开发中,XML的解析有很多选择,iOS SDK提供了NSXMLParser和libxml2两个类库,另外还有很多第三方类库可选,例如TBXML、TouchXML、KissXML、TinyXML和GDataXML。这篇文章使用了NSXMLParser。
解析 XML 通常有两种方式,DOM 和 SAX:
DOM解析XML时,读入整个XML文档并构建一个驻留内存的树结构(节点树),通过遍历树结构可以检索任意XML节点,读取它的属性和值。而且通常情况下,可以借助XPath,直接查询XML节点。
SAX解析XML,是基于事件通知的模式,一边读取XML文档一边处理,不必等整个文档加载完之后才采取操作,当在读取解析过程中遇到需要处理的对象,会发出通知对其进行处理。
NSXMLParser是基于SAX的解析方式。NSXMLParser采用了委托设计模式,因此他的实现类需要采用协议并支持委托。NSXMLParser解析XML需要委托NSXMLParserDelegate实现。
1、初始化NSXMLParser
要使用NSXMLParser要先创建它,设置各种属性,主要用到以下几个方法:
initWithContentsOfURL 通过NSURL创建解析器
initWithData 通过NSData创建解析器
setDelegate 为解析器定义委托
parse 运行解析器
[cpp] view
plaincopyprint?
NSXMLParser *parser=[[NSXMLParser alloc] initWithData:[xml dataUsingEncoding:NSUTF8StringEncoding]];
NSXMLParser *parser=[[NSXMLParser alloc] initWithContentsOfURL:[NSURL URLWithString:@"http://earthquake.usgs.gov/earthquakes/catalogs/7day-M2.5.xml"]];
[parser setDelegate:self];//设置NSXMLParser对象的解析方法代理
[parser setShouldProcessNamespaces:NO];
[parser parse];//开始解析
2、委托方法
主要使用一下委托方法:
[cpp] view
plaincopyprint?
//发现元素开始符的处理函数 (即报告元素的开始以及元素的属性)
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
//处理标签包含内容字符 (报告元素的所有或部分内容)
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
//发现元素结束符的处理函数,保存元素各项目数据(即报告元素的结束标记)
- (void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
//报告解析的结束
- (void)parserDidEndDocument:(NSXMLParser *)parser
//报告不可恢复的解析错误
- (void)paser:parserErrorOccured
// xml文件的样式 的样式有多种样式,标准的是把数据存放在子节点中,还有就是比较简单的读取就是把数据直接存在属性里面
// 第一种,这是自己写出来的一种,把数据存储在子节点中,读取相对麻烦一些
// 第二种是从中国气象网的api上街区出来的一段,是把数据存储在了属性中,比较容易读取数据
// 下面是解析第一种样式的代码:
// 头文件
#import
@interface RootViewController : UIViewController<</span>NSXMLParserDelegate>
#pragma mark - 声明--属性
@property (nonatomic, retain) NSMutableArray *messageeListArray; // 数据存储的地方
@property (nonatomic, retain) NSString *fromTagFlag; // 开始标签
@end
// 实现文件
#import "RootViewController.h"
@interface RootViewController ()
@end
@implementation RootViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// 获取xml字符串类型文件名
NSString *xmlDocPath = [[NSBundle mainBundle] pathForResource:@"document"ofType:@"xml"];
// 把字符串类型的网址转为NSURL类型
NSURL *url =[[NSURL alloc] initFileURLWithPath:xmlDocPath];
// 使用url实例化网络请求实例
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 同步读取到网络上的数据
NSData *urlData = [NSURLConnection sendSynchronousRequest:requestreturningResponse:nil error:nil];
// 实例化一个具体的解析类对象
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:urlData];
// 设置该解析类对象的代理
xmlParser.delegate = self;
// 调用方法开始解析xml文件
[xmlParser parse];
}
#pragma mark - NSXMLParser Delegate -
#pragma mark 文档开始读取
- (void)parserDidStartDocument:(NSXMLParser *)parser {
// 实例化存储数据的数组
self.messageeListArray = [NSMutableArray array];
}
#pragma mark 解析标签开始
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
// 首先用属性fromTagFlag获取ElementName,供后面使用
self.fromTagFlag = elementName;
// 判断
if ([elementName isEqualToString:@"Message"]) {
NSString *identifier = [attributeDict objectForKey:@"id"];
NSMutableDictionary *oneDic = [NSMutableDictionary dictionary];
[oneDic setObject:identifier forKey:@"id"];
[self.messageeListArray addObject:oneDic];
}
}
#pragma mark 获取到标签对应的数据
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
// 剔除获取的文本中空格和换行
string = [string stringByTrimmingCharactersInSet:[NSCharacterSetwhitespaceAndNewlineCharacterSet]];
NSMutableDictionary *dict = [self.messageeListArray lastObject];
// 判断from标签
if ([_fromTagFlag isEqualToString:@"from"] &&
dict) {
[dict setObject:string forKey:@"from"];
}
// 判断CDate标签
if ([_fromTagFlag isEqualToString:@"CDate"] &&
dict) {
[dict setObject:string forKey:@"CDate"];
}
// 判断Content标签
if ([_fromTagFlag isEqualToString:@"Content"]
&& dict) {
[dict setObject:string forKey:@"Content"];
}
}
#pragma mark - 解析标签结束
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
self.fromTagFlag = nil;
}
#pragma mark 文档结束读取
- (void)parserDidEndDocument:(NSXMLParser *)parser {
// 打印获取到的数据的数组
NSLog(@"%@", self.messageeListArray);
}
#pragma mark - 重写----dealloc方法
- (void)dealloc {
[_messageeListArray release], _messageeListArray = nil;
[_fromTagFlag release], _fromTagFlag = nil;
// 调用父类的dealloc方法
[super dealloc];
}
@end
// 第二种xml样式解析的代码
// 头文件
#import
@interface RootViewController : UIViewController<</span>NSXMLParserDelegate>
#pragma mark - 声明--属性
@property (nonatomic, retain) NSMutableArray *messageeListArray; // 数据存储的地方
@property (nonatomic, retain) NSString *fromTagFlag; // 开始标签
@end
// 实现文件
#import "RootViewController.h"
@interface RootViewController ()
@end
@implementation RootViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// 准备网址的字符串数据
NSString *urlString =@"http://flash.weather.com.cn/wmaps/xml/beijing.xml";
// 把字符串类型的网址转为NSURL类型
NSURL *url1 = [[NSURL alloc] initWithString:urlString];
// 使用url实例化网络请求实例
NSURLRequest *request = [NSURLRequest requestWithURL:url1];
// 同步读取到网络上的数据
NSData *urlData = [NSURLConnection sendSynchronousRequest:requestreturningResponse:nil error:nil];
// 实例化一个具体的解析类对象
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:urlData];
// 设置该解析类对象的代理
xmlParser.delegate = self;
// 调用方法开始解析xml文件
[xmlParser parse];
}
#pragma mark - NSXMLParser Delegate -
#pragma mark 文档开始读取
- (void)parserDidStartDocument:(NSXMLParser *)parser {
// 实例化存储数据的数组
self.messageeListArray = [NSMutableArray array];
}
#pragma mark 解析标签开始
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
// 首先用属性fromTagFlag获取ElementName,供后面使用
self.fromTagFlag = elementName;
// 因为数据都是存储在属性中的,全都存储在了attributeDict里面了,在这里直接打印下
NSLog(@"%@", attributeDict);
}
#pragma mark 获取到标签对应的数据
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
// 因为数据都存储在了属性中,所有不需要解析子标签
}
#pragma mark - 解析标签结束
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
self.fromTagFlag = nil;
}
#pragma mark 文档结束读取
- (void)parserDidEndDocument:(NSXMLParser *)parser {
// 打印获取到的数据的数组
NSLog(@"%@", self.messageeListArray);
}
#pragma mark - 重写----dealloc方法
- (void)dealloc {
[_messageeListArray release], _messageeListArray = nil;
[_fromTagFlag release], _fromTagFlag = nil;
// 调用父类的dealloc方法
[super dealloc];
}
@end
解析 XML 通常有两种方式,DOM 和 SAX:
DOM解析XML时,读入整个XML文档并构建一个驻留内存的树结构(节点树),通过遍历树结构可以检索任意XML节点,读取它的属性和值。而且通常情况下,可以借助XPath,直接查询XML节点。
SAX解析XML,是基于事件通知的模式,一边读取XML文档一边处理,不必等整个文档加载完之后才采取操作,当在读取解析过程中遇到需要处理的对象,会发出通知对其进行处理。
NSXMLParser是基于SAX的解析方式。NSXMLParser采用了委托设计模式,因此他的实现类需要采用协议并支持委托。NSXMLParser解析XML需要委托NSXMLParserDelegate实现。
1、初始化NSXMLParser
要使用NSXMLParser要先创建它,设置各种属性,主要用到以下几个方法:
initWithContentsOfURL 通过NSURL创建解析器
initWithData 通过NSData创建解析器
setDelegate 为解析器定义委托
parse 运行解析器
[cpp] view
plaincopyprint?
NSXMLParser *parser=[[NSXMLParser alloc] initWithData:[xml dataUsingEncoding:NSUTF8StringEncoding]];
NSXMLParser *parser=[[NSXMLParser alloc] initWithContentsOfURL:[NSURL URLWithString:@"http://earthquake.usgs.gov/earthquakes/catalogs/7day-M2.5.xml"]];
[parser setDelegate:self];//设置NSXMLParser对象的解析方法代理
[parser setShouldProcessNamespaces:NO];
[parser parse];//开始解析
2、委托方法
主要使用一下委托方法:
[cpp] view
plaincopyprint?
//发现元素开始符的处理函数 (即报告元素的开始以及元素的属性)
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
//处理标签包含内容字符 (报告元素的所有或部分内容)
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
//发现元素结束符的处理函数,保存元素各项目数据(即报告元素的结束标记)
- (void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
//报告解析的结束
- (void)parserDidEndDocument:(NSXMLParser *)parser
//报告不可恢复的解析错误
- (void)paser:parserErrorOccured
// xml文件的样式 的样式有多种样式,标准的是把数据存放在子节点中,还有就是比较简单的读取就是把数据直接存在属性里面
// 第一种,这是自己写出来的一种,把数据存储在子节点中,读取相对麻烦一些
// 第二种是从中国气象网的api上街区出来的一段,是把数据存储在了属性中,比较容易读取数据
// 下面是解析第一种样式的代码:
// 头文件
#import
@interface RootViewController : UIViewController<</span>NSXMLParserDelegate>
#pragma mark - 声明--属性
@property (nonatomic, retain) NSMutableArray *messageeListArray; // 数据存储的地方
@property (nonatomic, retain) NSString *fromTagFlag; // 开始标签
@end
// 实现文件
#import "RootViewController.h"
@interface RootViewController ()
@end
@implementation RootViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// 获取xml字符串类型文件名
NSString *xmlDocPath = [[NSBundle mainBundle] pathForResource:@"document"ofType:@"xml"];
// 把字符串类型的网址转为NSURL类型
NSURL *url =[[NSURL alloc] initFileURLWithPath:xmlDocPath];
// 使用url实例化网络请求实例
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 同步读取到网络上的数据
NSData *urlData = [NSURLConnection sendSynchronousRequest:requestreturningResponse:nil error:nil];
// 实例化一个具体的解析类对象
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:urlData];
// 设置该解析类对象的代理
xmlParser.delegate = self;
// 调用方法开始解析xml文件
[xmlParser parse];
}
#pragma mark - NSXMLParser Delegate -
#pragma mark 文档开始读取
- (void)parserDidStartDocument:(NSXMLParser *)parser {
// 实例化存储数据的数组
self.messageeListArray = [NSMutableArray array];
}
#pragma mark 解析标签开始
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
// 首先用属性fromTagFlag获取ElementName,供后面使用
self.fromTagFlag = elementName;
// 判断
if ([elementName isEqualToString:@"Message"]) {
NSString *identifier = [attributeDict objectForKey:@"id"];
NSMutableDictionary *oneDic = [NSMutableDictionary dictionary];
[oneDic setObject:identifier forKey:@"id"];
[self.messageeListArray addObject:oneDic];
}
}
#pragma mark 获取到标签对应的数据
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
// 剔除获取的文本中空格和换行
string = [string stringByTrimmingCharactersInSet:[NSCharacterSetwhitespaceAndNewlineCharacterSet]];
NSMutableDictionary *dict = [self.messageeListArray lastObject];
// 判断from标签
if ([_fromTagFlag isEqualToString:@"from"] &&
dict) {
[dict setObject:string forKey:@"from"];
}
// 判断CDate标签
if ([_fromTagFlag isEqualToString:@"CDate"] &&
dict) {
[dict setObject:string forKey:@"CDate"];
}
// 判断Content标签
if ([_fromTagFlag isEqualToString:@"Content"]
&& dict) {
[dict setObject:string forKey:@"Content"];
}
}
#pragma mark - 解析标签结束
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
self.fromTagFlag = nil;
}
#pragma mark 文档结束读取
- (void)parserDidEndDocument:(NSXMLParser *)parser {
// 打印获取到的数据的数组
NSLog(@"%@", self.messageeListArray);
}
#pragma mark - 重写----dealloc方法
- (void)dealloc {
[_messageeListArray release], _messageeListArray = nil;
[_fromTagFlag release], _fromTagFlag = nil;
// 调用父类的dealloc方法
[super dealloc];
}
@end
// 第二种xml样式解析的代码
// 头文件
#import
@interface RootViewController : UIViewController<</span>NSXMLParserDelegate>
#pragma mark - 声明--属性
@property (nonatomic, retain) NSMutableArray *messageeListArray; // 数据存储的地方
@property (nonatomic, retain) NSString *fromTagFlag; // 开始标签
@end
// 实现文件
#import "RootViewController.h"
@interface RootViewController ()
@end
@implementation RootViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// 准备网址的字符串数据
NSString *urlString =@"http://flash.weather.com.cn/wmaps/xml/beijing.xml";
// 把字符串类型的网址转为NSURL类型
NSURL *url1 = [[NSURL alloc] initWithString:urlString];
// 使用url实例化网络请求实例
NSURLRequest *request = [NSURLRequest requestWithURL:url1];
// 同步读取到网络上的数据
NSData *urlData = [NSURLConnection sendSynchronousRequest:requestreturningResponse:nil error:nil];
// 实例化一个具体的解析类对象
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:urlData];
// 设置该解析类对象的代理
xmlParser.delegate = self;
// 调用方法开始解析xml文件
[xmlParser parse];
}
#pragma mark - NSXMLParser Delegate -
#pragma mark 文档开始读取
- (void)parserDidStartDocument:(NSXMLParser *)parser {
// 实例化存储数据的数组
self.messageeListArray = [NSMutableArray array];
}
#pragma mark 解析标签开始
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
// 首先用属性fromTagFlag获取ElementName,供后面使用
self.fromTagFlag = elementName;
// 因为数据都是存储在属性中的,全都存储在了attributeDict里面了,在这里直接打印下
NSLog(@"%@", attributeDict);
}
#pragma mark 获取到标签对应的数据
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
// 因为数据都存储在了属性中,所有不需要解析子标签
}
#pragma mark - 解析标签结束
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
self.fromTagFlag = nil;
}
#pragma mark 文档结束读取
- (void)parserDidEndDocument:(NSXMLParser *)parser {
// 打印获取到的数据的数组
NSLog(@"%@", self.messageeListArray);
}
#pragma mark - 重写----dealloc方法
- (void)dealloc {
[_messageeListArray release], _messageeListArray = nil;
[_fromTagFlag release], _fromTagFlag = nil;
// 调用父类的dealloc方法
[super dealloc];
}
@end
相关文章推荐
- teradata PI -- 数据检索
- Python查看微信被哪些好友删除, 不用群发
- 线性回归分析中的哑变量
- 从头认识java-17.4 详解同步(3)-对象锁
- php 提交网页 传值 获取编辑框的值
- eclipse配置tomcat,访问http://localhost:8080时,出现404错误
- 史上最臭名昭著五大软件Bug
- vb编程中的选择结构语句的写法
- 我的前端历程开端
- 彻底解决 LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
- Android换肤系列 Activity资源拦截与替换
- Java Web系列:Spring Boot 基础 (转)
- 【Objective-C学习记录】第四十天
- MySQL - 主从复制及读写分离原理
- Ibatis学习总结6--使用 SQL Map API 编程
- 关于未知单播泛洪故障以及最佳实践
- Java连接池优化 DBCP/C3P0
- linux一些基础知识
- static和final 关键字
- pygame入门笔记