iOS基础--数据解析(XML)

来源:互联网 发布:投资入门知乎 编辑:程序博客网 时间:2024/06/14 20:11

在开发的时候一般都是使用JSON数据,解析方便,体积小,但是XML的基本使用还是必须要掌握的,希望能够通过阅读这篇文章帮助读者初步了解iOS开发中XML文档的解析方法,在了解XML的解析之前,有必要先说说什么是XML?

XML

一种用于标记电子文件使其具有结构性的标记语言。(百度百科)

跟JSON一样,XML也是经常使用的一种用于交互的数据格式,简单的来说,一个XML文档需要由以下几部分组成:
- 文档声明
- 元素(Element)
- 属性(Attribute)


文档声明:

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

这是一个最简单的xml文档声明,包括版本信息以及字符编码。


元素

一个XML元素包括一个开始标签和一个结束标签

<title>标题</title>

当然,一个元素也可以没有内容

<title></title>

此时我们就可以把他简写成

<title/>

元素也允许进行嵌套

<blog>    <title>我是标题</title>    <content>我是内容</content></blog>

其中,title和content元素为blog的子元素,虽说如此,但是元素也绝对不允许交叉嵌套
并且,一个规范的XML文档只能拥有一个根元素,其他元素都是这个根元素的子元素


属性

对于每一个元素,它可以拥有多个属性,或者没有属性

<blog title="标题" content="内容"/>

属性包括属性名和属性值,两者通过=连接,属性值需要使用“ ”或者‘ ’引用

通常我们也可以使用子元素来表示属性,


介绍了半天XML的格式,现在正式进入正题,如何解析XML:

XML解析:

在iOS的开发过程中,XML的解析方式主要有两种,今天主要介绍第二种:
- DOM:解析时会一次性将文件加载到内存中,文件体积越大越占内存,缺点越明显。
- SAX:从根元素开始一级级进行解析,使用灵活。

NSXMLParser:

苹果源生SDK,采用事件驱动(event-driven)模式,即SAX的方式来解析XML文档,当NSXMLParser在处理过程中,遇到特定的事件时会通知自身的代理,调用代理方法进行解析。

通常情况,解析一个XML需要以下步骤:

假设有一XML文档格式如下:

<books>    <book bookId="1">        <name>计算机网络</name>        <page>310</page>        <author>谢希仁</author>    </book>    <book bookId="2">        <name>数据结构</name>        <page>200</page>        <author>严蔚敏</author>    </book></books>
// 定义数据保存所有数据@property (nonatomic, strong) NSMutableArray *elements;// 定义字典保存正在处理的元素@property (nonatomic, strong) NSMutableDictionary *currentElement;// 定义字符串保存正在处理的内容@property (nonatomic, strong) NSMutableString *currentContent;

1.创建一个NSXMLParser对象,并设置代理:

// data通常为服务器返回的NSData类型的数据NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];// 设置代理为本地parser.delegate = self;// 开始解析BOOl isSucess = [parser parse];if (isSuccess) {    NSLog(@"获取xml文件成功");}else {    NSLog(@"获取xml文件失败");}

当然必不可少的,代理需要遵守NSXMLParserDelegate协议

2.当调用解析器的Parse方法之后,程序就会开始执行代理方法解析XML文档,此处介绍需要经常使用的代理方法:

/** *  开始解析文档的回调方法 */- (void)parserDidStartDocument:(NSXMLParser *)parser {    // 可以在此处初始化数组和字典以保存数据    ...}
/** *  开始解析某一元素 *  elementName:元素名 *  attributeDict:元素属性字典 */- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {    // 由于我们需要保存的是book对象,所以当解析到开始标记为book时,创建一个可变字典,设置它的bookId;    if ([elementName isEqualToString:@"book"]) {         self.currentElement = [NSMutableDictionary dictionary];        self.currentElement[@"bookId"] = attributeDict[@"bookId"];    }}
/** *  解析元素内容,当解析器找到了开始标记和结束标记之间的内容是会调用这个方法,视内容长度,该方法可能会被重复调用多次 */- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {    // 当解析器找到内容时,拼接内容到当前处理的字符串    [self.currentString appendString:string];}
/** *  结束解析某一元素 *  elementName:元素名 *  attributeDict:元素属性字典 */- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {    if ([elementName isEqualToString:@"book"]) {        // 如果找到了结束标记为book的元素,那么证明book元素以及它的所有子元素全部处理完毕,将处理完毕的book元素存入数组当中        [self.elements addObject:self.currentElement];        return;    }    // 如果标记不是book,说明此时处理完毕的元素是book元素的子元素,那么为当前处理的book元素赋值    self.currentElement[elementName] = self.currentString;    self.currentString = nil;}
/** *  结束解析文件 */- (void)parserDidEndDocument:(NSXMLParser *)parser {    ...}
/** *  解析出现错误时的回调方法 */- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {    NSLog(@"%@",parseError);}

NSXMLParser的好处在于其事件驱动的处理模式,条例清晰,可以在每一步骤进行对应的处理,刚看到可能会觉得很复杂,多加练习自然可以掌握。

0 0
原创粉丝点击