首页 > 其他 > 详细

XML的两种解析方式逐行解析(SAX解析)节点解析(DOM解析);

时间:2014-12-02 02:11:21      阅读:282      评论:0      收藏:0      [点我收藏+]

SAX逐行解析

SAXSimpleAPIfor XML。基于事件驱动的解析方式,逐行解析数据。(采用协议回调机制)

??NSXMLParseriOS自带的XML解析类。采用SAX方式解析数据

??解析过程由NSXMLParserDelegate协议方法回调

??解析过程:开始标签->取值->结束标签->取值

DOM解析

DOMDocumentObjectModel(文档对象模型)。解析时需要将XML文件整体读入,并且将XML结构化成树状,使用时再通过树状结构读取相关数据

??GDataXMLNode(这个类在下载包里面)Google提供的开源XML解析类,对libxml2.dylib进行了ObjectiveC的封装

??采用DOM方式解析数据

??iOS中包含一个C语言的动态链接库libxml2.dylib,解析速度比NSXMLParser

?

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
AppDelegate.m
#import?"AppDelegate.h"
#import?"MainViewController.h"
@implementation?AppDelegate
-?(BOOL)application:(UIApplication?*)application?didFinishLaunchingWithOptions:(NSDictionary?*)launchOptions
{
????self.window?=?[[UIWindow?alloc]?initWithFrame:[[UIScreen?mainScreen]?bounds]];
????//?Override?point?for?customization?after?application?launch.
????self.window.backgroundColor?=?[UIColor?whiteColor];
????[self.window?makeKeyAndVisible];
?????
?????
????MainViewController?*mainVC?=?[[MainViewController?alloc]?init];
????UINavigationController?*naviVC?=?[[UINavigationController?alloc]?initWithRootViewController:mainVC];
????self.window.rootViewController?=?naviVC;
????[naviVC?release];
????[mainVC?release];
?????
????[_window?release];
????return?YES;
}
-?(void)dealloc
{
????[_window?release];
????[super?dealloc];
}
-?(void)applicationWillResignActive:(UIApplication?*)application
{
????//?Sent?when?the?application?is?about?to?move?from?active?to?inactive?state.?This?can?occur?for?certain?types?of?temporary?interruptions?(such?as?an?incoming?phone?call?or?SMS?message)?or?when?the?user?quits?the?application?and?it?begins?the?transition?to?the?background?state.
????//?Use?this?method?to?pause?ongoing?tasks,?disable?timers,?and?throttle?down?OpenGL?ES?frame?rates.?Games?should?use?this?method?to?pause?the?game.
}
-?(void)applicationDidEnterBackground:(UIApplication?*)application
{
????//?Use?this?method?to?release?shared?resources,?save?user?data,?invalidate?timers,?and?store?enough?application?state?information?to?restore?your?application?to?its?current?state?in?case?it?is?terminated?later.?
????//?If?your?application?supports?background?execution,?this?method?is?called?instead?of?applicationWillTerminate:?when?the?user?quits.
}
-?(void)applicationWillEnterForeground:(UIApplication?*)application
{
????//?Called?as?part?of?the?transition?from?the?background?to?the?inactive?state;?here?you?can?undo?many?of?the?changes?made?on?entering?the?background.
}
-?(void)applicationDidBecomeActive:(UIApplication?*)application
{
????//?Restart?any?tasks?that?were?paused?(or?not?yet?started)?while?the?application?was?inactive.?If?the?application?was?previously?in?the?background,?optionally?refresh?the?user?interface.
}
-?(void)applicationWillTerminate:(UIApplication?*)application
{
????//?Called?when?the?application?is?about?to?terminate.?Save?data?if?appropriate.?See?also?applicationDidEnterBackground:.
}
@end

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
MainViewController.m
??
#import?"MainViewController.h"
#import?"XMLSAXParser.h"
#import?"JSONParser.h"
@interface?MainViewController?()
@end
@implementation?MainViewController
-?(id)initWithNibName:(NSString?*)nibNameOrNil?bundle:(NSBundle?*)nibBundleOrNil
{
????self?=?[super?initWithNibName:nibNameOrNil?bundle:nibBundleOrNil];
????if?(self)?{
????????//?Custom?initialization
????}
????return?self;
}
-?(void)viewDidLoad
{
????[super?viewDidLoad];
????//?Do?any?additional?setup?after?loading?the?view.
????self.view.backgroundColor?=?[UIColor?cyanColor];
?????
????//XML??SAX解析(逐行解析)
????XMLSAXParser?*parser?=?[[XMLSAXParser?alloc]?init];
????[parser?startParse];
????NSLog(@"解析后的%@",parser.array);
????[parser?release];
}
-?(void)didReceiveMemoryWarning
{
????[super?didReceiveMemoryWarning];
????//?Dispose?of?any?resources?that?can?be?recreated.
}
/*
#pragma?mark?-?Navigation
//?In?a?storyboard-based?application,?you?will?often?want?to?do?a?little?preparation?before?navigation
-?(void)prepareForSegue:(UIStoryboardSegue?*)segue?sender:(id)sender
{
????//?Get?the?new?view?controller?using?[segue?destinationViewController].
????//?Pass?the?selected?object?to?the?new?view?controller.
}
*/
@end

?

?

1
2
3
4
5
6
7
8
XMLSAXParser.h
#import?<Foundation/Foundation.h>
@interface?XMLSAXParser?:?NSObject<NSXMLParserDelegate>
@property?(nonatomic?,?retain)NSMutableArray?*array;????//装学生对象
@property?(nonatomic?,?retain)NSString?*tempStr;???//临时健在节点内容
-?(void)startParse;??//开始解析,逐行解析
-?(void)startDOMParse;?//开始dom解析,按节点解析
@end

?

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
XMLSAXParser.m
#import?"XMLSAXParser.h"
#import?"Student.h"
#import?"GDataXMLNode.h"
@implementation?XMLSAXParser
//XML解析:逐行解析
-?(void)startParse;
{
????//XML解析:逐行解析
?????
????//从文件列表中读取数据
????//1.获取文件路径
????NSString?*sourcePath?=?[[NSBundle?mainBundle]?pathForResource:@"Student"?ofType:@"xml"];
????//2.通过路径把文件转换成NSData类型
????NSData?*data?=?[NSData?dataWithContentsOfFile:sourcePath];
?????
????//创建的时候需要给parser一个字符串数据(NSData)
????NSXMLParser?*parser?=?[[NSXMLParser?alloc]?initWithData:data];
?????
????//设定代理人
????parser.delegate?=?self;
????//开始对文件进行解析
????[parser?parse];
????//内存管理
????[parser?release];
?????
}
-?(void)parser:(NSXMLParser?*)parser?didStartElement:(NSString?*)elementName?namespaceURI:(NSString?*)namespaceURI?qualifiedName:(NSString?*)qName?attributes:(NSDictionary?*)attributeDict
{
????//当找到节点头的时候,体统调用这个方法
????NSLog(@"节点头");
?????
????if?([elementName?isEqualToString:@"students"])?{
????????//当找到students节点头的时候,初始化数组
????????self.array?=?[NSMutableArray?array];
????}else?if?([elementName?isEqualToString:@"student"]){
????????//当找到student节点时候,创建一个新的学生对象,添加到数组中
????????Student?*stu?=?[[Student?alloc]?init];
????????[self.array?addObject:stu];
????????[stu?release];
?????????
????}
}
-?(void)parser:(NSXMLParser?*)parser?foundCharacters:(NSString?*)string
{
????//当找到节点内容的时候,调用
????NSLog(@"节点内容");
????//把内容保存起来,只要碰到节点内容,下一个肯定是节点尾
????self.tempStr?=?string;
}
-?(void)parser:(NSXMLParser?*)parser?didEndElement:(NSString?*)elementName?namespaceURI:(NSString?*)namespaceURI?qualifiedName:(NSString?*)qName
{
????//当找到节点尾时候调用
????NSLog(@"节点尾");
?????
????//取得之前保存的student对象
????Student?*stu?=?[self.array?lastObject];???//核心代码,懂了没?.........
????if?([elementName?isEqualToString:@"name"])?{
????????stu.name?=?self.tempStr;
????}else?if?([elementName?isEqualToString:@"sex"]){
????????stu.sex?=?self.tempStr;
????}else?if?([elementName?isEqualToString:@"phone"]){
????????stu.phone?=?self.tempStr;
????}else?if?([elementName?isEqualToString:@"number"]){
????????stu.number?=?self.tempStr;
????}
}
//开始dom解析,按节点解析
-?(void)startDOMParse
{
????//按节点解析
????//1.获取要解析文件的文件信息
????NSString?*xmlPath?=?[[NSBundle?mainBundle]pathForResource:@"Student"?ofType:@"xml"];
????NSData?*data?=?[NSData?dataWithContentsOfFile:xmlPath];
?????
????//参数1:要解析的xml串
????//参数2:随便
????//参数3:错误信息
????GDataXMLDocument?*doc?=?[[GDataXMLDocument?alloc]?initWithData:data?options:0?error:nil];
?????
????//2.获取文件的根节点
????GDataXMLElement?*rootElement?=?[doc?rootElement];
?????
????//3.进一步搜索所有的子节点
????//返回一个装满了student节点(GDataXMLElement对象)的数组
????NSArray?*array?=?[rootElement?elementsForName:@"student"];
?????
????self.array?=?[NSMutableArray?array];
????//4.遍历数组,把student节点的每个子节点取出来
????for?(GDataXMLElement?*element?in?array)?{
?????????
????????Student?*stu?=?[[Student?alloc]?init];
?????????
????????GDataXMLElement?*nameElement?=?[[element?elementsForName:@"name"]lastObject];
?????????
????????//从name节点中取值
????????NSString?*name?=?[nameElement?stringValue];
?????????
????????//给学生对象的属性赋值
????????stu.name?=?name;
?????????
????????//把学生对象添加到数组中-----------其他的雷同
????????[self.array?addObject:stu];
????????[stu?release];
????}
}
@end

?

1
2
3
4
5
6
7
8
9
Student.h
??
#import?<Foundation/Foundation.h>
@interface?Student?:?NSObject
@property?(nonatomic?,?retain)NSString?*number;
@property?(nonatomic?,?retain)NSString?*name;
@property?(nonatomic?,?retain)NSString?*sex;
@property?(nonatomic?,?copy)NSString?*phone;
@end

Student.m

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#import?"Student.h"
@implementation?Student
-?(void)dealloc
{
????[_name?release];
????[_number?release];
????[_sex?release];
????[_phone?release];
????[super?dealloc];
}
//当这个类的对象被NSLog输出时候,系统会先调用这个方法,如果这个方法被重写,就直接输出重写的内容,否则就输出系统默认的内容
-?(NSString?*)description
{
????return?[NSString?stringWithFormat:@"name:%@?sex:%@?phone:%@?number:%@",?self.name,?self.sex,?self.phone,?self.number];
}
@end

?

这里需要注意的是添加第三方类的步骤:

直接添加第三方类是有错的

?

GDataXMLNode.h

// libxml includes require that the target Header Search Paths contain

//

// ? /usr/include/libxml2

//

// and Other Linker Flags contain

//

// ? -lxml2

?

在下面的对上面的文件中首先搜索Header Search?然后在第二行中添加上/usr/include/libxml2

然后同理搜索Other Linker然后在第二行中添加上-lxml2

这样第三方类就可以使用了?.

?

?

XML在不同的语言里解析方式都是一样的,只不过实现的语法不同而已。基本的解析方式有两种,一种叫SAX,另一种叫DOM。SAX是基于事件流的解析,DOM是基于XML文档树结构的解析.假设我们XML的内容和结构如下:?

?

[xhtml]?view plaincopy

?

1
2
3
4
5
6
7
8
<?xml?version="1.0"?encoding="UTF-8"?>??
<employees>???
<employee>???
<name>ddviplinux</name>???
<sex>m</sex>???
<age>30</age>???
</employee>???
</employees>

下面是解析XMl常用的Dom和Sex方法:

1.DOM生成和解析XML文档

为 XML 文档的已解析版本定义了一组接口。解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以使用 DOM 接口来操作这个树结构。优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)。?

?

[java]?view plaincopy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public?void?parserXml(String?fileName)?{???
??try?{???
????DocumentBuilderFactory?dbf?=?DocumentBuilderFactory.newInstance();??
????DocumentBuilder?db?=?dbf.newDocumentBuilder();???
????Document?document?=?db.parse(fileName);???
????NodeList?employees?=?document.getChildNodes();???
????for?(int?i?=?0;?i?<?employees.getLength();?i++)?{???
??????Node?employee?=?employees.item(i);???
??????NodeList?employeeInfo?=?employee.getChildNodes();???
??????for?(int?j?=?0;?j?<?employeeInfo.getLength();?j++)?{???
????????Node?node?=?employeeInfo.item(j);???
????????NodeList?employeeMeta?=?node.getChildNodes();???
????????for?(int?k?=?0;?k?<?employeeMeta.getLength();?k++)?{???
??????????System.out.println(employeeMeta.item(k).getNodeName()?+?":"?+?employeeMeta.item(k).getTextContent());???
????????}???
??????}???
????}??
????System.out.println("解析完毕");??
??}?catch?(Exception?e)?{???
??????System.out.println(e.getMessage());???
??}??
}

?

  • ?

?

2.SAX生成和解析XML文档

为解决DOM的问题,出现了SAX。SAX ,事件驱动。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。优点:不用事先调入整个文档,占用资源少;SAX解析器代码比DOM解析器代码小,适于Applet,下载。缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;使用场合:Applet;只需XML文档的少量内容,很少回头访问;机器内存少;

?

?

[java]?view plaincopy

?

1
2
3
4
5
6
7
8
9
10
public?void?parserXml(String?fileName)?{???
??SAXParserFactory?saxfac?=?SAXParserFactory.newInstance();???
??try?{???
????SAXParser?saxparser?=?saxfac.newSAXParser();???
????InputStream?is?=?new?FileInputStream(fileName);???
????saxparser.parse(is,?new?MySAXHandler());???
??}?catch?(Exception?e)?{???
????e.printStackTrace();???
??}???
}

XML的两种解析方式逐行解析(SAX解析)节点解析(DOM解析);

原文:http://aijuans.iteye.com/blog/2162277

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!