IOS 解析XML文档

前段时间想找点事做,就是试着看能不能用豆瓣的API做点什么,于是就碰到了这个问题——XML解析。

  老师还没讲,只能自己去查。

  XML文档解析主要有SAX和DOM两种模式,IOS上两种模式都可以用,这里就不做过多介绍,我选择的SAX模式。

IOS解析XML用的是自带的NSXML框架,框架的核心是NSXMLParser类和它的委托协议NSXMLParserDelegate,其主要的解析工作是在NSXMLParserDelegate实现类中完成的。委托中定义了许多回掉方法,在SAX解析器从上到下遍历XML文档的过程中,遇到开始标签、结束标签、文档开始、文档结束和字符串结束是就会触发这些方法。这些方法有很多,下面我们列出5个常用的方法。

在文档开始时触发

 -(void)parserDidStartDocument:(NSXMLParser *)parser      

  遇到一个新标签是触发,其中namespaceURI是命名空间,qualifiedName是限定名,attributes是字典类型的属性集合。

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 

  找到字符串时触发

    -(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string

  遇到结束标签时触发

    -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 

  在文档结束时触发

-(void)parserDidEndDocument:(NSXMLParser *)parser         

下面通过一个具体的例子来看整个的调用与解析过程

首先这是我们将要解析的XML文件 "info.xml"

    ?    ?    ?<?xml version="1.0" encoding="UTF-8"?>

    ?    ?    ?<root>  ?    ?

    ?    ?    ?    ? <person id="1">

    ?    ?    ?    ?    ? <firstName>Wythe</firstName>
   ?    ?    ?    ?    ?
    ?    ?    ?    ?    ? <lastName>xu</lastName>
   ?    ?    ?    ?    ?
    ?    ?    ?    ?    ? <age>22</age>  ?    ?    ?    ?

    ?    ?    ?    ? </person>
  ?    ?    ?
   ?    ?    ?    ? <person id="2">
   ?    ?    ?    ?
    ?    ?    ?    ?    ? <firstName>li</firstName>
    ?    ?    ?    ?    ?
    ?    ?    ?    ?    ? <lastName>si</lastName>
    ?    ?    ?    ?    ?
    ?    ?    ?    ?    ? <age>31</age>
  ?    ?    ?    ?
    ?    ?    ?    ? </person>
    ?    ?    ?    ?
    ?    ?    ?    ?    ?<person id="3">
   ?    ?    ?    ?    ?
    ?    ?    ?    ?    ? <firstName>Dipen</firstName>
    ?    ?    ?    ?    ?
    ?    ?    ?    ?    ? <lastName>Shah</lastName>
    ?    ?    ?    ?    ?
    ?    ?    ?    ?    ? <age>24</age>
    ?    ?    ?    ?
    ?    ?    ?    ? </person>
    ?    ?    ?    ?
    ?    ?    ?</root>

接来来是一个头文件 "ViewController.h"

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController<NSXMLParserDelegate>

@property NSXMLParser *parser;
@property NSMutableArray *person;
@property NSString *currenttag;

@end

然后是它的实现文件  "ViewController.m"

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

@synthesize  parser = _parser , person = _person , currenttag = _currenttag;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSString *xmlFilePath = [[NSBundle mainBundle]pathForResource:@"info"ofType:@"xml"];

    NSData *data = [[NSData alloc]initWithContentsOfFile:xmlFilePath];

    self.parser = [[NSXMLParser alloc]initWithData:data];

    self.parser.delegate = self;

    [self.parser parse];

    NSLog(@"%@",_person);

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark delegate method

-(void)parserDidStartDocument:(NSXMLParser *)parser
{
    _person = [[NSMutableArray alloc]init];
    NSLog(@"start parse 1");
}

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    _currenttag = elementName;

    if ([_currenttag isEqualToString:@"person"]) {
        NSString *_id = [attributeDict objectForKey:@"id"];
        NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
        [dict setObject:_id forKey:@"id"];
        [_person addObject:dict];
    }

    NSLog(@"start element");
}

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    NSMutableDictionary *dict = [_person lastObject];

    if ([_currenttag isEqualToString:@"firstName"] && dict) {
        [dict setObject:string forKey:@"firstName"];

    }
    if ([_currenttag isEqualToString:@"lastName"] && dict) {
        [dict setObject:string forKey:@"lastName"];
    }
    if ([_currenttag isEqualToString:@"age"] && dict) {
        [dict setObject:string forKey:@"age"];
    }

    NSLog(@"found characters");
}

-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    _currenttag = nil;

    NSLog(@"end element");
}

-(void)parserDidEndDocument:(NSXMLParser *)parser
{
    NSLog(@"parse end");
}
@end

通过断电和输出信息,我们可以知道整个解析过程是 开始解析文档、开始标签、找到字符串、结束标签、文档结束。

2014-09-10 16:45:32.920 xmlforblog[3820:60b] start parse 1
2014-09-10 16:45:32.921 xmlforblog[3820:60b] start element
2014-09-10 16:45:32.922 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.922 xmlforblog[3820:60b] start element
2014-09-10 16:45:32.922 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.922 xmlforblog[3820:60b] start element
2014-09-10 16:45:32.923 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.923 xmlforblog[3820:60b] end element
2014-09-10 16:45:32.923 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.923 xmlforblog[3820:60b] start element
2014-09-10 16:45:32.924 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.924 xmlforblog[3820:60b] end element
2014-09-10 16:45:32.924 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.924 xmlforblog[3820:60b] start element
2014-09-10 16:45:32.925 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.925 xmlforblog[3820:60b] end element
2014-09-10 16:45:32.925 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.925 xmlforblog[3820:60b] end element
2014-09-10 16:45:32.926 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.926 xmlforblog[3820:60b] start element
2014-09-10 16:45:32.928 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.929 xmlforblog[3820:60b] start element
2014-09-10 16:45:32.929 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.929 xmlforblog[3820:60b] end element
2014-09-10 16:45:32.930 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.930 xmlforblog[3820:60b] start element
2014-09-10 16:45:32.930 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.930 xmlforblog[3820:60b] end element
2014-09-10 16:45:32.931 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.931 xmlforblog[3820:60b] start element
2014-09-10 16:45:32.931 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.931 xmlforblog[3820:60b] end element
2014-09-10 16:45:32.931 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.932 xmlforblog[3820:60b] end element
2014-09-10 16:45:32.932 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.932 xmlforblog[3820:60b] start element
2014-09-10 16:45:32.932 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.933 xmlforblog[3820:60b] start element
2014-09-10 16:45:32.933 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.933 xmlforblog[3820:60b] end element
2014-09-10 16:45:32.933 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.934 xmlforblog[3820:60b] start element
2014-09-10 16:45:32.934 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.934 xmlforblog[3820:60b] end element
2014-09-10 16:45:32.934 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.935 xmlforblog[3820:60b] start element
2014-09-10 16:45:32.935 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.935 xmlforblog[3820:60b] end element
2014-09-10 16:45:32.935 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.936 xmlforblog[3820:60b] end element
2014-09-10 16:45:32.936 xmlforblog[3820:60b] found characters
2014-09-10 16:45:32.936 xmlforblog[3820:60b] end element
2014-09-10 16:45:32.936 xmlforblog[3820:60b] parse end
2014-09-10 16:45:32.936 xmlforblog[3820:60b] (
        {
        age = 22;
        firstName = Wythe;
        id = 1;
        lastName = xu;
    },
        {
        age = 31;
        firstName = li;
        id = 2;
        lastName = si;
    },
        {
        age = 24;
        firstName = Dipen;
        id = 3;
        lastName = Shah;
    }
)

执行结果

而我们的处理主要是在 开始标签、找到字符串 (

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string

中。

遇到开始标签时,我们现判断标签,名字,如果是person,表明接下来就是person的信息,这样我们就先创建一个可变字典,以便将来存放它的值。

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    _currenttag = elementName;

    if ([_currenttag isEqualToString:@"person"]) {
        NSString *_id = [attributeDict objectForKey:@"id"];
        NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
        [dict setObject:_id forKey:@"id"];
        [_person addObject:dict];
    }

    NSLog(@"start element");
}

在找到字符串时,我们就是通过判断当前标签名,将对应的信息保存到刚刚创建的字典中

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    NSMutableDictionary *dict = [_person lastObject];

    if ([_currenttag isEqualToString:@"firstName"] && dict) {
        [dict setObject:string forKey:@"firstName"];

    }
    if ([_currenttag isEqualToString:@"lastName"] && dict) {
        [dict setObject:string forKey:@"lastName"];
    }
    if ([_currenttag isEqualToString:@"age"] && dict) {
        [dict setObject:string forKey:@"age"];
    }

    NSLog(@"found characters");
}

不断循环这样的过程,最后我们就可以解析出整个XML文档。

另外说一句,这只是解析一般的文档,如果你跟我曾经一样学会这个就去解析豆瓣API的XML文档,会发现行不通。这时因为许多网站因为它的数据较多,为了避免标签的重复,使用了命名空间,带有命名空间的XML文档解析和这稍有不同。

以后我会写带命名空间的XML文档解析,敬请期待。

拖了快一个月了,今天终于写完。以后不能这么懒了

?

时间: 2025-01-11 15:28:21

IOS 解析XML文档的相关文章

四种生成和解析XML文档的方法详解

众所周知,现在解析XML的方法越来越多,但主流的方法也就四种,即:DOM.SAX.JDOM和DOM4J 一.介绍及优缺点分析 1. DOM(Document Object Model) DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准.DOM是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在树中寻找特定信息.分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作.由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的. [优点]      ①允许应用

浅谈用java解析xml文档(四)

继续接上一文,这一阵子因为公司项目加紧,导致最后一个解析xml文档的方式,还没有总结,下面总结使用dom4J解析xml. DOM4J(Document Object Model for Java) 使用dom4j解析,个人认为是四种解析方式里面最方便的一种,DOM4J是一个非常非常优秀的Java XML API,具有性能优异.功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件.如今你可以看到越来越多的Java软件都在使用DOM4J来读写XML,特别值得一提的是连Sun的JAXM也在用D

浅谈用java解析xml文档(三)

接上一篇,本文介绍使用JDOM解析xml文档, 首先我们还是应该知道JDOM从何而来,是Breet Mclaughlin和Jason Hunter两大Java高手的创作成果,2000年初, JDOM作为一个开放源代码项目正式开始研发.JDOM是一种解析XML的Java工具包. JDOM基于树状结构,利用纯JAVA技术对XML文档实现解析.生成.序列化及其它操作. 我们从以下步骤开始解析: (1).通过JDOM的API创建一个SAXBuilder的对象 SAXBuilder saxBuilder

Java 解析XML文档

一.解析XML文档方式: 1.DOM方式:将整个XML文档读取到内存中,按照XML文件的树状结构图进行解析. 2.SAX方式:基于事件的解析,只需要加载XML中的部分数据,优点是,占用资源更少,内存消耗小. XML文档: <?xml version="1.0" encoding="UTF-8"?> <students> <student> <name>张三</name> <age>20</

原生javascript解析xml文档

之前写过一篇 <javascript/jQuery解析或转换json和xml>链接是http://my.oschina.net/ososchina/blog/343748,这篇博客详细解释了json使用 JSON.js  window.eval() ,jQuery 与字符串互相转换的方法 ,顺便也说了一点jQuery解析xml文档的方法,这里着重论述javascript操作xml. 顺便提一下,今天做项目有一点问题,如何让服务程序接口返回的就是json,而不需要 使用 jQuery.ajax设

Android解析XML文档的两种方式的简单对比

Android之所以会用到解析XML文档,不仅与JAVA对XML的解析比较简单,而且还因为XML是Android在网络间传递信息的主要存储方式.下面我简单谈谈Android对XML文档解析的两种方式:dom和sax.dom解析方式是,解析方法将一个XML文件看成是一棵树.由数据结构的知识我们知道对树的处理比较简单,就是对树的节点进行增,删,改,查,这也是dom的一个最大优点.但是,dom方式在解析的时候是一次性就将整个XML文档读进内存,这坏处不用我说了吧,我宝贵的内存是禁不起这么折腾的. sa

浅谈用java解析xml文档(二)

上一文中总结了dom解析xml文档的方式,本文开始总结使用SAX解析xml 的方式及它的优缺点! SAX(Simple API for XML),是指一种接口,或者一个软件包. 首先我们应该知道SAX解析和dom解析的区别: dom是树结构解析,易于理解和开发,它可以随意访问文件所在的节点位置,易于修改,删除和查询.但对于dom文档过大时,则会解析较慢. 而SAX解析是事件推动型,顺序读取文件的节点,且只能读取文档的内容,不能对文档的内容进行修噶,对文档的大小没有过多的限制,但开大复杂度较高,

网络电视精灵~分析~~~~~~简单工厂模式,继承和多态,解析XML文档

小总结: 所用技术: 01.C/S架构,数据存储在XML文件中 02.简单工厂模式 03.继承和多态 04.解析XML文档技术 05.深入剖析内存中数据的走向 06.TreeView控件的使用 核心:通过该项目,我们对业务流程有一个整体把控.对继承和多态有深入的了解 下面是类图: 主界面图: 核心思路: 1   1.首先在频道管理类ChannelManager中写一个加载所有频道方法LoadAllChannel; 2   3        该方法作用读取FullChannels.xml文件,并且

org.w3c.dom(java dom)解析XML文档

位于org.w3c.dom操作XML会比较简单,就是将XML看做是一颗树,DOM就是对这颗树的一个数据结构的描述,但对大型XML文件效果可能会不理想 首先来了解点Java DOM 的 API:1.解析器工厂类:DocumentBuilderFactory 创建的方法:DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 2.解析器:DocumentBuilder 创建方法:通过解析器工厂类来获得 DocumentBu