今天利用多余时间研究了一下XML文档解析,虽然现在移动端使用的数据格式基本为JSON格式,但是XML格式毕竟多年来一直在各种计算机语言之间使用,是一种老牌的经典的灵活的数据交换格式。所以我认为还是很有必要认真学习一下。

<?xml version="1.0" encoding="UTF-8"?>
<Notes>
<Note id="">
<CDate>-2-</CDate>
<Content>早上8点钟到公司</Content>
<UserID>jack</UserID>
</Note>
<Note id="">
<CDate>-3-1</CDate>
<Content>早上8点到公司</Content>
<UserID>jack</UserID>
</Note>
<Note id="">
<CDate>-3-</CDate>
<Content>早上九点到公司</Content>
<UserID>jack</UserID>
</Note>
<Note id="">
<CDate>-3-3</CDate>
<Content>早上十点到公司</Content>
<UserID>jack</UserID>
</Note>
<Note id="">
<CDate>-3-4</CDate>
<Content>中午一点到公司</Content>
<UserID>jack</UserID>
</Note>
<Note id="">
<CDate>-3-5</CDate>
<Content>中午两点到公司</Content>
<UserID>jack</UserID>
</Note>
</Notes>

这是一个简单的XML文档,结构由声明、根元素<notes> 根元素只有一个,开始和结束标签必须一致、子元素、属性、命名空间、限定名组成,所有元素都要有结束标签,开始和结束标签必须一致。具体就不多做介绍了,我把重点放在XML文档的解析上。

读写XML文档目前最流行的有两种方式:

(1)SAX 一种基于事件驱动的解析模式,解析XML时程序从上到下读取XML文档,如果遇到开始标签结束标签属性等,就会触发相应的事件。弊端只能读取XML文档不能写入,优点是解析速度快。

(2)DOM 将XML文档作为一棵树状结构进行分析,提供获取节点的内容以及相关属性,或者是增、删、改节点的内容。在加载时会一次性读入到内存中,如果文档比较大,解析速度就会很慢,所以苹果推荐使用SAX模式。

介绍两个实例:

(1)使用NSXML

NSXML是iOS SDK 自带的,也是苹果默认解析框架,采用SAX模式。核心是NSXMLParser和它的委托协议NSXMLParserDelegate。

@interface NotesXMLParser : NSObject<NSXMLParserDelegate>

@property (nonatomic, strong) NSMutableArray *notes;
/*
* 当前标签名字
*/
@property (nonatomic, strong) NSString *currentTagName; - (void) start;
@end
- (void)start
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"Notes" ofType:@"xml"];
NSURL *url = [NSURL fileURLWithPath:path];
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
parser.delegate = self;
[parser parse];
} #pragma mark - <NSXMLParserDelegate>
//文档开始时触发
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
_notes = [NSMutableArray array];
}
//文档出错时触发
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
NSLog(@"error:%@",parseError.localizedDescription);
}
//遇到一个开始标签时触发
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict
{
_currentTagName = elementName;
if ([_currentTagName isEqualToString:@"Note"]){
NSString *_id = [attributeDict objectForKey:@"id"];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:_id forKey:@"id"];
[_notes addObject:dict];
}
}
//遇到字符串时触发
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];//替换回车符和空格
if ([string isEqualToString:@""]){
return;
}
NSMutableDictionary *dict = [_notes lastObject];
if ([_currentTagName isEqualToString:@"CDate"] && dict){
[dict setObject:string forKey:@"CDate"];
}
if ([_currentTagName isEqualToString:@"Content"] && dict){
[dict setObject:string forKey:@"Content"];
}
if ([_currentTagName isEqualToString:@"UserID"] && dict){
[dict setObject:string forKey:@"UserID"];
}
}
//遇到结束标签时触发
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
self.currentTagName = nil;
}
//遇到文档结束时触发
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
[[NSNotificationCenter defaultCenter] postNotificationName:@"reloadViewNotification" object:self.notes userInfo:nil];
self.notes = nil;
}

(2)使用TBXML

TBXML解析文档采用DOM模式,通上面比较使用起来比较方便。githup地址:https://githup.com/71squared/TBXML,下载完成后需要在源码工程头文件MyNotes-Prefix.pch中添加宏定义:#define ARC_ENABLED,注意添加.pch文件路径,参考:http://www.ithao123.cn/content-9982088.html 。添加libz.tbd依赖库。

代码实现部分:

@interface NotesTBXMLParser : NSObject

@property (nonatomic, strong) NSMutableArray *notes;

- (void)start;

@end
@implementation NotesTBXMLParser

- (void)start
{
_notes = [NSMutableArray array];
TBXML *tbxml = [[TBXML alloc] initWithXMLFile:@"Notes.xml" error:nil];
TBXMLElement *root = tbxml.rootXMLElement;//获取文档根元素对象
if (root) {
TBXMLElement *noteElement = [TBXML childElementNamed:@"Note" parentElement:root];//通过根元素找到下面的note元素
while (noteElement != nil) {//note元素有很多 遍历循环
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
//通过noteElement找到下面的子元素
TBXMLElement *CDateElement = [TBXML childElementNamed:@"CDate" parentElement:noteElement];
if (CDateElement != nil) {
NSString *CDate = [TBXML textForElement:CDateElement];
[dict setObject:CDate forKey:@"CDate"];
} TBXMLElement *ContentElement = [TBXML childElementNamed:@"Content" parentElement:noteElement];
if (ContentElement != nil) {
NSString *Content = [TBXML textForElement:ContentElement];
[dict setObject:Content forKey:@"Content"];
} TBXMLElement *UserIDElement = [TBXML childElementNamed:@"UserID" parentElement:noteElement];
if (UserIDElement != nil) {
NSString *UserID = [TBXML textForElement:UserIDElement];
[dict setObject:UserID forKey:@"UserID"];
}
//获得id属性
NSString *_id = [TBXML valueOfAttributeNamed:@"id" forElement:noteElement error:nil];
[dict setObject:_id forKey:@"id"]; [_notes addObject:dict]; noteElement = [TBXML nextSiblingNamed:@"Note" searchFromElement:noteElement];//获取同层下个note元素,通过sibling可看出非父子关系的同级元素
}
}
NSLog(@"解析完成");
[[NSNotificationCenter defaultCenter] postNotificationName:@"reloadViewNotification" object:self.notes];
self.notes = nil;
} @end

iOS网络编程笔记——XML文档解析的更多相关文章

  1. iOS 网络编程:XML解析

    1 XML文档结构 1.1 简介 XML 指可扩展标记语言(eXtensible Markup Language).XML 被设计用来传输和存储数据.其非常像HTML的标记语言,但与之不同的是,XML ...

  2. jsoup -- xml文档解析

    jsoup -- xml文档解析 修改 https://jsoup.org/cookbook/modifying-data/set-attributes https://jsoup.org/cookb ...

  3. xml文档解析

    XML文档解主要分为四种解析方式,官方提供的两种分别是:DOM 和 SAX,第三方分别是:JDOM 和 DOM4j 测试用的xml文档: <?xml version="1.0" ...

  4. Android XML文档解析(一)——SAX解析

    ---------------------------------------------------------------------------------------------------- ...

  5. JAVA读取XML,JAVA读取XML文档,JAVA解析XML文档,JAVA与XML,XML文档解析(Document Object Model, DOM)

    使用Document Object Model, DOM解析XML文档 也可参考我的新浪博客:http://blog.sina.com.cn/s/blog_43ac5543010190w3.html ...

  6. XML 文档解析操作

    sing System;using System.Data;using System.Configuration;using System.Web;using System.Web.Security; ...

  7. iOS网络编程笔记——Socket编程

    一.什么是Socket通信: Socket是网络上的两个程序,通过一个双向的通信连接,实现数据的交换.这个双向连路的一端称为socket.socket通常用来实现客户方和服务方的连接.socket是T ...

  8. C++MFC编程笔记day05 文档类-单文档和多文档应用程序

    文档类 1 相关类    CDocument类-父类是CCmdTarget类,所以,文档类也能够处理菜单等               命令消息. 作用保存和管理数据.    注意事项:怎样解决断言错 ...

  9. iOS网络编程笔记——社交网络编程

    社交网络编程主要使用iOS提供的social框架,目前social框架主要分为两个类: (1)SLComposeViewController提供撰写社交信息(如微博信息)的视图控制器,由iOS系统提供 ...

随机推荐

  1. linux系统下find删除目录下除一文件外的所有文件

    /data/目录下有a.txt b.txt c.txt d.txt删除/data/目录下所有文件,保留b.txt两种方法:1.[root@xuegod62 ~]# find /data/ -type ...

  2. GreenOpenPaint的实现(一)基本框架

    Win7下的MSPaint是Ribbon的典型运行.这种SDI程序对于图像处理来说是很适合的.利用春节时间,基于之前的积累,我实现GreenOpenPaint,主要就是模拟MSPaint的界面,实现出 ...

  3. 在ubuntu下编写python(python入门)

    在ubuntu下编写python 一般情况下,ubuntu已经安装了python,打开终端,直接输入python,即可进行python编写. 默认为python2 如果想写python3,在终端输入p ...

  4. 【java设计模式】之 建造者(Builder)模式

    我们还是举上一节的例子:生产汽车.上一节我们通过模板方法模式控制汽车跑起来的动作,那么需求是无止境的,现在如果老板又增加了额外的需求:汽车启动.停止.鸣笛引擎声都由客户自己控制,他想要什么顺序就什么顺 ...

  5. Leaflet+heatmap实现离线地图加载和热力图应用

    本人博客主页:http://www.cnblogs.com/webbest/ 2017年春节已经过完,新一年的奋斗也刚刚开始.今年要经历的挑战也是大大的...不扯了. 年底前软件项目相对较多,恰巧在年 ...

  6. CSS3知识点整理(三)----变形与动画

    一.CSS3中的变形 1)旋转 rotate() rotate()函数通过指定的角度参数使元素相对原点进行旋转. 它主要在二维空间内进行操作,设置一个角度值,用来指定旋转的幅度. 如果这个值为正值,元 ...

  7. 关于下载SAE日志签名认证的方法——PHP版

    之前需要下载SAE上的日志存入数据库,因此研究了下SAE的签名认证和日志下载.这个链接是SAE官方给出的API文档.https://www.sinacloud.com/doc/api.html#qia ...

  8. [Usaco2014 Open]Gold Fair Photography(hash)

    最近做了usaco2014 open的金组,果然美帝的题还是没有太简单啊QAQ,被每年的月赛骗了QAQ 不过话说官方题解真心棒(虽然英文的啃得好艰难,我英语渣你们别鄙视我= =),标程超级优美QAQ ...

  9. [Kafka] - Kafka Java Consumer实现(一)

    Kafka提供了两种Consumer API,分别是:High Level Consumer API 和 Lower Level Consumer API(Simple Consumer API) H ...

  10. 单线程JavaScript

    最近在阅读<你不知道的JavaScript中卷>,当我看到第二部分介绍异步和回调函数的一些知识时,由于该书在第二部分1.2章对线程.事件循环的概念介绍的并非详细,因此引发了我的一系列思考. ...