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();
- }
- }