SAX逐行解析

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

NSXMLParser是iOS自带的XML解析类。采用SAX方式解析数据

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

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

DOM解析

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

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

采用DOM方式解析数据

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

AppDelegate.m#import"AppDelegate.h"#import"MainViewController.h"@implementationAppDelegate-(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions{self.window=[[UIWindowalloc]initWithFrame:[[UIScreenmainScreen]bounds]];//Overridepointforcustomizationafterapplicationlaunch.self.window.backgroundColor=[UIColorwhiteColor];[self.windowmakeKeyAndVisible];MainViewController*mainVC=[[MainViewControlleralloc]init];UINavigationController*naviVC=[[UINavigationControlleralloc]initWithRootViewController:mainVC];self.window.rootViewController=naviVC;[naviVCrelease];[mainVCrelease];[_windowrelease];returnYES;}-(void)dealloc{[_windowrelease];[superdealloc];}-(void)applicationWillResignActive:(UIApplication*)application{//Sentwhentheapplicationisabouttomovefromactivetoinactivestate.Thiscanoccurforcertaintypesoftemporaryinterruptions(suchasanincomingphonecallorSMSmessage)orwhentheuserquitstheapplicationanditbeginsthetransitiontothebackgroundstate.//Usethismethodtopauseongoingtasks,disabletimers,andthrottledownOpenGLESframerates.Gamesshouldusethismethodtopausethegame.}-(void)applicationDidEnterBackground:(UIApplication*)application{//Usethismethodtoreleasesharedresources,saveuserdata,invalidatetimers,andstoreenoughapplicationstateinformationtorestoreyourapplicationtoitscurrentstateincaseitisterminatedlater.//Ifyourapplicationsupportsbackgroundexecution,thismethodiscalledinsteadofapplicationWillTerminate:whentheuserquits.}-(void)applicationWillEnterForeground:(UIApplication*)application{//Calledaspartofthetransitionfromthebackgroundtotheinactivestate;hereyoucanundomanyofthechangesmadeonenteringthebackground.}-(void)applicationDidBecomeActive:(UIApplication*)application{//Restartanytasksthatwerepaused(ornotyetstarted)whiletheapplicationwasinactive.Iftheapplicationwaspreviouslyinthebackground,optionallyrefreshtheuserinterface.}-(void)applicationWillTerminate:(UIApplication*)application{//Calledwhentheapplicationisabouttoterminate.Savedataifappropriate.SeealsoapplicationDidEnterBackground:.}@end


MainViewController.m#import"MainViewController.h"#import"XMLSAXParser.h"#import"JSONParser.h"@interfaceMainViewController()@end@implementationMainViewController-(id)initWithNibName:(NSString*)nibNameOrNilbundle:(NSBundle*)nibBundleOrNil{self=[superinitWithNibName:nibNameOrNilbundle:nibBundleOrNil];if(self){//Custominitialization}returnself;}-(void)viewDidLoad{[superviewDidLoad];//Doanyadditionalsetupafterloadingtheview.self.view.backgroundColor=[UIColorcyanColor];//XMLSAX解析(逐行解析)XMLSAXParser*parser=[[XMLSAXParseralloc]init];[parserstartParse];NSLog(@"解析后的%@",parser.array);[parserrelease];}-(void)didReceiveMemoryWarning{[superdidReceiveMemoryWarning];//Disposeofanyresourcesthatcanberecreated.}/*#pragmamark-Navigation//Inastoryboard-basedapplication,youwilloftenwanttodoalittlepreparationbeforenavigation-(void)prepareForSegue:(UIStoryboardSegue*)seguesender:(id)sender{//Getthenewviewcontrollerusing[seguedestinationViewController].//Passtheselectedobjecttothenewviewcontroller.}*/@end


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



XMLSAXParser.m#import"XMLSAXParser.h"#import"Student.h"#import"GDataXMLNode.h"@implementationXMLSAXParser//XML解析:逐行解析-(void)startParse;{//XML解析:逐行解析//从文件列表中读取数据//1.获取文件路径NSString*sourcePath=[[NSBundlemainBundle]pathForResource:@"Student"ofType:@"xml"];//2.通过路径把文件转换成NSData类型NSData*data=[NSDatadataWithContentsOfFile:sourcePath];//创建的时候需要给parser一个字符串数据(NSData)NSXMLParser*parser=[[NSXMLParseralloc]initWithData:data];//设定代理人parser.delegate=self;//开始对文件进行解析[parserparse];//内存管理[parserrelease];}-(void)parser:(NSXMLParser*)parserdidStartElement:(NSString*)elementNamenamespaceURI:(NSString*)namespaceURIqualifiedName:(NSString*)qNameattributes:(NSDictionary*)attributeDict{//当找到节点头的时候,体统调用这个方法NSLog(@"节点头");if([elementNameisEqualToString:@"students"]){//当找到students节点头的时候,初始化数组self.array=[NSMutableArrayarray];}elseif([elementNameisEqualToString:@"student"]){//当找到student节点时候,创建一个新的学生对象,添加到数组中Student*stu=[[Studentalloc]init];[self.arrayaddObject:stu];[sturelease];}}-(void)parser:(NSXMLParser*)parserfoundCharacters:(NSString*)string{//当找到节点内容的时候,调用NSLog(@"节点内容");//把内容保存起来,只要碰到节点内容,下一个肯定是节点尾self.tempStr=string;}-(void)parser:(NSXMLParser*)parserdidEndElement:(NSString*)elementNamenamespaceURI:(NSString*)namespaceURIqualifiedName:(NSString*)qName{//当找到节点尾时候调用NSLog(@"节点尾");//取得之前保存的student对象Student*stu=[self.arraylastObject];//核心代码,懂了没.........if([elementNameisEqualToString:@"name"]){stu.name=self.tempStr;}elseif([elementNameisEqualToString:@"sex"]){stu.sex=self.tempStr;}elseif([elementNameisEqualToString:@"phone"]){stu.phone=self.tempStr;}elseif([elementNameisEqualToString:@"number"]){stu.number=self.tempStr;}}//开始dom解析,按节点解析-(void)startDOMParse{//按节点解析//1.获取要解析文件的文件信息NSString*xmlPath=[[NSBundlemainBundle]pathForResource:@"Student"ofType:@"xml"];NSData*data=[NSDatadataWithContentsOfFile:xmlPath];//参数1:要解析的xml串//参数2:随便//参数3:错误信息GDataXMLDocument*doc=[[GDataXMLDocumentalloc]initWithData:dataoptions:0error:nil];//2.获取文件的根节点GDataXMLElement*rootElement=[docrootElement];//3.进一步搜索所有的子节点//返回一个装满了student节点(GDataXMLElement对象)的数组NSArray*array=[rootElementelementsForName:@"student"];self.array=[NSMutableArrayarray];//4.遍历数组,把student节点的每个子节点取出来for(GDataXMLElement*elementinarray){Student*stu=[[Studentalloc]init];GDataXMLElement*nameElement=[[elementelementsForName:@"name"]lastObject];//从name节点中取值NSString*name=[nameElementstringValue];//给学生对象的属性赋值stu.name=name;//把学生对象添加到数组中-----------其他的雷同[self.arrayaddObject:stu];[sturelease];}}@end

Student.h#import<Foundation/Foundation.h>@interfaceStudent:NSObject@property(nonatomic,retain)NSString*number;@property(nonatomic,retain)NSString*name;@property(nonatomic,retain)NSString*sex;@property(nonatomic,copy)NSString*phone;@end

Student.m

#import"Student.h"@implementationStudent-(void)dealloc{[_namerelease];[_numberrelease];[_sexrelease];[_phonerelease];[superdealloc];}//当这个类的对象被NSLog输出时候,系统会先调用这个方法,如果这个方法被重写,就直接输出重写的内容,否则就输出系统默认的内容-(NSString*)description{return[NSStringstringWithFormat:@"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

<?xmlversion="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

publicvoidparserXml(StringfileName){try{DocumentBuilderFactorydbf=DocumentBuilderFactory.newInstance();DocumentBuilderdb=dbf.newDocumentBuilder();Documentdocument=db.parse(fileName);NodeListemployees=document.getChildNodes();for(inti=0;i<employees.getLength();i++){Nodeemployee=employees.item(i);NodeListemployeeInfo=employee.getChildNodes();for(intj=0;j<employeeInfo.getLength();j++){Nodenode=employeeInfo.item(j);NodeListemployeeMeta=node.getChildNodes();for(intk=0;k<employeeMeta.getLength();k++){System.out.println(employeeMeta.item(k).getNodeName()+":"+employeeMeta.item(k).getTextContent());}}}System.out.println("解析完毕");}catch(Exceptione){System.out.println(e.getMessage());}}



2.SAX生成和解析XML文档

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


[java]view plaincopy

publicvoidparserXml(StringfileName){SAXParserFactorysaxfac=SAXParserFactory.newInstance();try{SAXParsersaxparser=saxfac.newSAXParser();InputStreamis=newFileInputStream(fileName);saxparser.parse(is,newMySAXHandler());}catch(Exceptione){e.printStackTrace();}}