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]copy
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文档的少量内容,很少回头访问;机器内存少;
copy
publicvoidparserXml(StringfileName){ SAXParserFactorysaxfac=SAXParserFactory.newInstance(); try{ SAXParsersaxparser=saxfac.newSAXParser(); InputStreamis=newFileInputStream(fileName); saxparser.parse(is,newMySAXHandler()); }catch(Exceptione){ e.printStackTrace(); } }