UI_16 XML、JSON数据结构解析

非 Y 不嫁゛ 提交于 2019-12-15 18:47:20

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

     从事先规定好的格式中提取数据,即为解析。iOS开发常见的解析有:XML解析、JSON解析

一、XML解析

     XML:Extensible Markup language(可扩展标记语⾔),主流数 据格式之⼀,可以⽤来存储和传输数据。

     XML的解析有很多选择,iOS SDK提供了NSXMLParser和libxml2两个类库,另外还有很多第三方类库可选,例如TBXML、TouchXML、KissXML、TinyXML和GDataXML。如何选择?

  • 如果是读取很小的XML文档,性能基本上没有什么差别,不过从调用的方便性来说,建议使用TouchXML、KissXML或GDataXML

  • 如果是需要读取和修改XML文档,建议使用KissXML或GDataXML

  • 如果需要读取非常大的XML文档,则建议使用libxml2、NSXMLParser或TBXML

更多XML解析选择性问题请看 iOS平台XML解析类库对比和安装说明


1、XML数据结构

Student文件内容:

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

    <student>

        <name>张三</name>

        <number>1</number>
        <address>
如家401</address>
    </student>
    <student>
        <name>
傻逼</name>
        <number>3</number>
        <address>
如家403</address>
    </student>
    <student>
        <name>
二货</name>
        <number>2</number>
        <address>
如家402</address>
    </student>

</students>


2、SAX解析

     SAX:Simple API for XML。基于事件驱动的解析⽅式,逐⾏解析 数据。(采⽤协议回调机制)

2.1NSXMLParser

     NSXMLParser是iOS⾃带的XML解析类。采⽤SAX⽅式解析数据。

     解析过程由NSXMLParserDelegate协议⽅法回调

     解析过程:开始标签->取值->结束标签->取值


2.2示例

使用xib添加UIButton并关联didClickSAX:事件

在延展中声明实例变量_currentElementName接收开始标签的名字

声明属性studentsArray用来存储YFStudent模型

遵守 NSXMLParserDelegate协议并实现必要的方法

@interface ViewController ()<NSXMLParserDelegate>
{
   
NSString *_currentElementName;  //用来临时接收开始标签的名字
}
@property(nonatomic, retain) NSMutableArray *studentsArray;

- (IBAction)didClickSAX:(UIButton *)sender;

@end

实现部分的代码如下:

#pragma mark -- 使用SAX方式解析XML,采用的是协议回调机制,逐行解析数据,使用NSXMLParser --
- (IBAction)didClickSAX:(UIButton *)sender {
   
//1.获取文件

    NSString *path = [[NSBundle mainBundle] pathForResource:@"Students" ofType:nil];

    //2.根据文件路径获取文件中的数据,并将其转换为NSData类型的数据

    NSData *data = [NSData dataWithContentsOfFile:path];

    //3.解析数据
   
//3.1创建解析数据的工具对象
   
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
   
//3.2设置代理
    parser.
delegate = self;
   
//3.3开始解析
    [parser
parse];
}

#pragma mark -- NSXMLParserDelegate --
//1.开始、结束解析文档
- (
void)parserDidStartDocument:(NSXMLParser *)parser
{
   
self.studentsArray = [NSMutableArray array];
   
NSLog(@"%s", __FUNCTION__);

}

- (void)parserDidEndDocument:(NSXMLParser *)parser
{
   
NSLog(@"%s", __FUNCTION__);

}

//2.解析元素
- (
void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
   
_currentElementName = elementName;
   
NSLog(@"%s, %@", __FUNCTION__, elementName);
   
if ([elementName isEqualToString:@"student"]) {
       
YFStudent *student = [[YFStudent alloc] init];
        [
_studentsArray addObject:student];
        [student
release];
    }

}   //“开始标签

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
   
//执行顺序:开始标签-取值-结束标签-取值;若不置空,结束标签后的换行符会覆盖之前的值
   
_currentElementName = nil;
   
NSLog(@"%s", __FUNCTION__);
   
NSLog(@"%s, %@", __FUNCTION__, elementName);

}   //“结束标签

//3.取标签后的值
- (
void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
   
YFStudent *student = [_studentsArray lastObject];
    [student
setValue:string forKey:_currentElementName];
   
NSLog(@"%s, %@", __FUNCTION__, string);

}


3、DOM解析

     DOM:Document Object Model(⽂档对象模型)。解析时需要 将XML⽂件整体读⼊,并且将XML结构化成树状,使⽤时再通过树 状结构读取相关数据


3.1GDataXMLNode

     GDataXMLNode采⽤DOM⽅式解析数据,是Google提供的开源XML解析类,对libxml2.dylib进⾏了Objective-C的封装。iOS中包含⼀个C语⾔的动态链接库libxml2.dylib,解析速度⽐NSXMLParser快但需要:

配置环境变量

由于GDataXML是非ARC的,因此得设置编译参数

3.2示例

在延展中声明属性studentsArray用来存储YFStudent模型

@property(nonatomic, retain) NSMutableArray *studentsArray;

在xib中添加按钮并关联事件

- (IBAction)didClickDOM:(UIButton *)sender;

实现解析

#pragma mark -- 使用DOM方式解析XML格式(会将整个xml文件读入内存,用数组以树状结构进行存放) --

- (IBAction)didClickDOM:(UIButton *)sender {

    //1.获取xml文件路径
   
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Students" ofType:nil];
   
//2.转换成NSData
   
NSData *data = [NSData dataWithContentsOfFile:filePath];
   
//3.解析
   
//3.1创建GDataXMLNode对象
   
NSError *error = nil;
   
GDataXMLDocument *xmlDocument = [[GDataXMLDocument alloc] initWithData:data options:0 error:&error];    //将整个data数据读入内存,存在GDataXMLDocument对象里(xmlDocument)

    NSMutableArray *stuArray = [NSMutableArray array];

    //3.2获得根节点

    GDataXMLElement *rootElement = xmlDocument.rootElement;
   
//3.3遍历节点
   
for (GDataXMLElement *childElement in rootElement.children) {
       
YFStudent *student = [[YFStudent alloc] init];
       
for (GDataXMLElement *element in childElement.children) {
           
//叶子节点值、标签名
            [student
setValue:element.stringValue forKey:element.name];
        }
        [stuArray
addObject:student];
    }

#warning mark -- 获取所有name节点中的值
    NSArray *nameArr = [xmlDocument nodesForXPath:@"//name" error:nil];
   
for (GDataXMLElement *element in nameArr) {
       
NSLog(@"%@", element.stringValue);

    } 

}



二、JSON解析

     Javascript Object Notation,轻量级的数据交换格式,采⽤完全 独⽴于语⾔的⽂本格式,被称为理想的数据交换语⾔。

     JSON解析⼯具:JSONKit、NSJSONSerialization、TouchJSON和SBJSON 等,其中NSJSONSerialization是系统提供的解析类,其解析效率是最⾼的

1、JSON数据结构

JSON⽂档有两种结构:对象、数组

  • 对象:以“{”开始,以“}”结束,是“名称/值”对⼉的集合。名称和值中间⽤“:”隔开。多个“名称/值”对之间⽤“”隔开。类似OC中的字典。

  • 数组:以“[”开始,以“]”结束,中间是数据。数据以“”分隔。

     JSON中的数据类型:字符串、数值、BOOL、对象、数组。


Teacher文件内容:

[{"name":"张三","number":"1","sex":""},{"name":"李四","number":"2","sex":""},{"name":"王五","number":"3","sex":""}]

结构太乱看不清?下面的工具会帮到你

http://www.bejson.com/jsonviewernew/

2、解析示例

#pragma mark -- JSON解析(NSJSONSerializationJSONKit方式) --

- (IBAction)didClickJSON:(UIButton *)sender {
   
//第一种:NSJSONSerialization
   
//1.path
   
NSString *path = [[NSBundle mainBundle] pathForResource:@"Teacher" ofType:nil];
   
//2.NSData
   
NSData *data = [NSData dataWithContentsOfFile:path];

    //3.解析

    NSMutableArray *array = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];    //关于options参数请看最后

    self.teachersArray = [NSMutableArray array];

    for (NSDictionary *dict in array) {

        YFTeacher *teacher = [[YFTeacher alloc] init];
       
        [teacher
setValuesForKeysWithDictionary:dict];
        [
_teachersArray addObject:teacher];
    }
   
   
for (YFTeacher *teacher in _teachersArray) {
       
NSLog(@"%@", [teacher description]);
    }

    //第二种:JSONKit

    NSMutableArray *array1 = [data objectFromJSONData]; //array1内容与上边array相同,之后过程略

    NSDictionary *dict = @{@"key":@[@"A",@"B",@"C"]};
   
//将字典转化为NSData类型的数据

    NSData *data1 = [dict JSONData];    //<7b226b65 79223a5b 2241222c 2242222c 2243225d 7d>
   
//将字典转化为NSString类型的数据
   
NSString *dictStr = [dict JSONString]; //{"key":["A","B","C"]}

}


关于NSJSONReadingOptions:

NSJSONReadingMutableContainers:返回可变容器,NSMutableDictionary或NSMutableArray。 

NSJSONReadingMutableLeaves:返回的JSON对象中字符串的值为NSMutableString,目前在iOS 7上测试不好用,应该是个bug,参见: 

http://stackoverflow.com/questions/19345864/nsjsonreadingmutableleaves-option-is-not-working 

NSJSONReadingAllowFragments:允许JSON字符串最外层既不是NSArray也不是NSDictionary,但必须是有效的JSON Fragment。例如使用这个选项可以解析 @“123” 这样的字符串。参见: 

http://stackoverflow.com/questions/16961025/nsjsonserialization-nsjsonreadingallowfragments-reading 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!