通过NSXMLParser来解析XML

NSXMLParser 使用 delegate 模型来解析 XML 内容的。下面我们来创建一个 XML 文 件,文件中包含如下内容(在工程中保存为 MyXML.xml):

<?xml version="1.0" encoding="UTF-8"?>
<root>
<person id="1">
    <firstName>zhang</firstName>
    <lastName>san</lastName>
    <age>51</age>
</person>

<person id="2">
    <firstName>li</firstName>
    <lastName>si</lastName>
    <age>61</age>
</person>

</root>
#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate,NSXMLParserDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (nonatomic, strong) NSXMLParser *xmlParser;

@end

可以看到,我定义了一个XML parser app delegate,并且尊循NSXMLParserDelegate协 议,该协议是作为 NSXMLParser 解析 xml 需要用到的 delegate。现在从磁盘中读取 MyXML.xml 文件,并将其传递给 XML 解析器:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //找到文件路径
    NSString *xmlFilePath = [[NSBundle mainBundle]pathForResource:@"MyXML" ofType:@"xml"];
    NSData *xml = [[NSData alloc]initWithContentsOfFile:xmlFilePath];
    self.xmlParser = [[NSXMLParser alloc]initWithData:xml];
    self.xmlParser.delegate = self;
    if ([self.xmlParser parse]) {
        NSLog(@"The XML is parsed");
    }else{
        NSLog(@"Failed to parse the XML");
    }
    return YES;
} 

  首先把文件内容读取到一个 NSData 实例对象中,然后使用 initWithData:来初始化我们 的 XML parser,并把我们从 xml 文件中读取出来的数据传递进去。之后我们可以调用 XML parser 的 parse 方法来开始解析处理。这个方法会阻塞当前线程,直至解析处理结束。如果 你需要解析的 XML 文件非常大,强烈建议使用一个全局的 dispatch 队列来进行解析。

  为了解析 XML 文件,我们需要了解定义在 NSXMLParserDelegate 协议中的代理方法和它们的职责:

  parserDidStartDocument:

  解析开始的时候调用该方法。

  

  parserDidEndDocument:

  解析结束的时候调用该方法。

  parser:didStartElement:namespaceURI:qualifiedName:attributes:

  在 XML document 中,当解析器在解析的时候遇到了一个新的 element 时会被调用该方法。

 

  parser:didEndElement:namespaceURI:qualifiedName:

  当前节点结束之后会调用。

 

  parser:foundCharacters:

  当解析器在解析文档内容的时候被调用。

在使用这些 delegate 方法的时候,我们可以为 XML 对象创建一个对象模型。下面我们定义一个对象来代表 XML element,类名叫做 XMLElement,代码如下:

#import <Foundation/Foundation.h>

@interface XMLElement : NSObject
@property (nonatomic, strong)NSString *name;
@property (nonatomic, strong)NSString *text;
@property (nonatomic, strong)NSDictionary *attributes;
@property (nonatomic, strong)NSMutableArray *subElements;
@property (nonatomic, weak) XMLElement *parent;
@end

.m

#import "XMLElement.h"

@implementation XMLElement
- (NSMutableArray *)subElements{
    //get方法 懒加载
    if (_subElements == nil) {
        _subElements = [[NSMutableArray alloc]init];
    }
    return _subElements;
}
@end

  我只想当访问 subElements 数组的时候,如果该数组是 nil,才进行初始化。因此我把这个属性的内存分配和初始化代码放到了它的getter方法中。如果说一个XML element没有子 elements,那么我们永远都不会使用到这个属性,因此这里也就不会为那个 element 分配内存和进行初始化工作。这种技术叫做 lazy allocation。 (懒加载)

  现在我们定义一个 XMLElement 实例,叫做 rootElement。我们的计划是开始解析处 理,向下获取 XML 文件内容并使用 delegate 方法进行解析,直至成功解析完整个文件。

#import <UIKit/UIKit.h>
@class XMLElement;
@interface AppDelegate : UIResponder <UIApplicationDelegate,NSXMLParserDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (nonatomic, strong) NSXMLParser *xmlParser;
@property (nonatomic, strong) XMLElement *rootElement;
@property (nonatomic, strong) XMLElement *currentElementPointer;
@end

开始解析处理。我们想要关注的第一个方法就是 parserDidStartDocument:方 法。在这个方法中,我们简单的重置一切:

//开始解析,重置
- (void)parserDidStartDocument:(NSXMLParser *)parser{
    self.rootElement = nil;
    self.currentElementPointer = nil;
}

下一个方法就是 parser:didStartElement:namespaceURI:qualifiedName:attributes:方法。在 这个方法中,如果root element没有被创建,会被创建,并且开始解析一个新的element,我 们会计算它在 XML 结构中的位置,并在当前 element 中添加一个新的 element。

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
    if (self.rootElement == nil) {
        self.rootElement = [[XMLElement alloc]init];
        self.currentElementPointer = self.rootElement;
    }else{
        XMLElement *newElement = [[XMLElement alloc]init];
        newElement.parent = self.currentElementPointer;
        [self.currentElementPointer.subElements addObject:newElement];
        self.currentElementPointer = newElement;
    }
    self.currentElementPointer.name = elementName;
    self.currentElementPointer.attributes = attributeDict;
}

下一步,就是 parser:foundCharacters: 这个方法了。这个方法将会在解析 element 的时 候调用多次,因此我们需要确保已经为多次进入该方法做好了准备。例如,如果一个 element 的文本有 4000 个字符长度,解析器在第一次解析时,最多只能解析 1000 个字符, 之后在解析当前 element 时,调用 parser:foundCharacters:方法,每次都是 1000,因此需要 4 次:

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
    if ([self.currentElementPointer.text length] > 0) {
        self.currentElementPointer.text = [self.currentElementPointer.text stringByAppendingString:string];
    }else{
        self.currentElementPointer.text = string;
    }
}

下一个需要关注的方法就是 parser:didEndElement:namespaceURI:qualifiedName:方法,当 解析至某个 element 尾部时,会调用该方法。在这里,我们只需要把当前 element 指针指向 当前 element 的上一级:

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
    self.currentElementPointer = self.currentElementPointer.parent;
}

最终,我们需要处理 parserDidEndDocument 这个方法。我们需要 dispose currentElementPointe 属性。

- (void)parserDidEndDocument:(NSXMLParser *)parser{
    self.currentElementPointer = nil;
}

上面就是所有的实现内容,现在你就可以使用 rootElement 属性来遍历 XML 结构了

时间: 2024-10-10 16:31:43

通过NSXMLParser来解析XML的相关文章

IOS开发使用NSXMLParser、GDataXML两种方式解析XML数据

概括:XML数据解析方式有 *IOS原生的NSXMLParser,只支持SAX方式解析,使用简单 *C语言的libxml2,同时支持DOM和SAX方式解析 *google的GDataXML,只支持DOM方式解析,基于libxml2,使用时需要将编译环境配置为非ARC,并添加libxml2.dylib动态库 GDataXMLDocument 1 使用GDataXML的DOM方式解析XML,需要导入#import "GDataXMLNode.h" /** *  DOM方式解析XML数据 *

XML专题:使用NSXMLParser解析xml文件

使用NSXMLParser解析xml文件 1. 设置委托对象,开始解析     NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];   //或者也可以使用initWithContentsOfURL直接下载文件,但是有一个原因不这么做:     // It's also possible to have NSXMLParser download the data, by passing it a URL, but this

iOS SDK中使用NSXMLParser解析XML(iphone网络篇三)

iOS SDK的NSXMLParser解析XML文档是事件驱动模式的,即采用SAX方式来解析XML格式文档.NSXMLParser在处理XML文档的过程中当遇到一些要素(元素.属性.CDATA块.评论等)时会通知它的委托,而自身不对解析的要素进行任何处理,全权委托给NSXMLParserDelegate处理.同时它也会报告错误. 1. 打开一个xml文件,读取内容到NSData中. NSString *path = [[NSBundle mainBundle] pathForResource:@

第十五讲.数据解析(XML与JSON两种数据解析)

一.XML数据解析 1.SAX:Simple API for XML.基于事件驱动的解析方式,逐行解析数据.(采用协议回调机制) NSXMLParser的解析方法: 1 #import "ViewController.h" 2 #import "Model.h" 3 4 @interface ViewController ()<NSXMLParserDelegate> 5 6 @property(nonatomic,strong)UITableView

NSXMLParser(SAX解析)

NSXMLParser(SAX解析) 一.使用步骤 // 传入XML数据,创建解析器 NSXMLParser*parser = [[NSXMLParser alloc] initWithData:data]; // 设置代理,监听解析过程 parser.delegate = self; // 开始解析 [parser parse]; 二.NSXMLParserDelegate NSXMLParser采取的是SAX方式解析,特点是事件驱动,下面情况都会通知代理 当扫描到文档的开始时调用(开始解析)

iOS多线程与网络开发之解析xml

郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 如果文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额随意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源码下载:点我传送 游戏官方下载:http://dwz.cn/RwTjl 游戏视频预览:http://dwz.cn/RzHHd 游戏开发博客:http://dwz.cn/RzJzI 游戏源码传送:http://dwz.cn/Nret1 A.XML基本知识 1.xml概念 什么是XML全称是Extensible Markup Lan

iOS解析XML数据

iOS中解析XML数据的类是  NSXMLParser,详细使用方法如下: 假设现在在内存中有XML的二进制数据对象(NSData):data(该数据可能来自网络,也可能是本地的文件数据),设置NSXMLParser对象的协议,代码如下: NSXMLParser *xmlParse = [[NSXMLParser alloc] initWithData:data]; [xmlParse setDelegate:self]; [xmlParse parse];// 解析开始 解析对象设置后,我们需

iOS开发之解析XML格式数据

XML格式的数据是一种数据的传输格式.因为它方便编写.结构清晰,所以深受程序猿的喜爱,非常多人都喜欢使用XML格式数据传输或者作为程序的配置信息. 如今我将来实如今iOS中解析XML格式数据,语言使用Swift. 首先自己写一个简单的XML: <data> <person age="15">zhangsan</person> <person age="2">lisi</person> <person&

iOS-数据解析XML解析的多种平台介绍

在iPhone开发中,XML的解析有很多选择,iOS SDK提供了NSXMLParser和libxml2两个类库,另外还有很多第三方类库可选,例如TBXML.TouchXML.KissXML.TinyXML和GDataXML.问题是应该选择哪一个呢? 解析 XML 通常有两种方式,DOM 和 SAX: DOM解析XML时,读入整个XML文档并构建一个驻留内存的树结构(节点树),通过遍历树结构可以检索任意XML节点,读取它的属性和值.而且通常情况下,可以借助XPath,直接查询XML节点. SAX