UI进阶——XML解析与Json解析

一、解析的基本概念

解析数据就是从事先准备好的数据格式中提取数据,常见的数据格式有XML和JSON数据格式。iOS对两种数据格式都提供了解析方式。

二、xml数据结构解析

xml:Extensible Markup Language(可扩展标记语言)。
下面是一段解析文件的示例:
<?xml version="1.0" encoding="utf-8"?> <!--此行包含XML的版本信息和编码格式-->
<students><!--这是开始标签,也就是根节点-->
	<student attribute = "六班吉祥物"><!--student为根节点的子节点,name节点的父节点, attribute是它的属性-->
		<name>李帅</name><!--洛洛受为name节点的值-->
		<sex>无</sex>
		<age>14</age>
	</student>
	<student attribute = "吉祥物之基友">
		<name>建华</name>
		<sex>随条件改变</sex>
		<age>17</age>
	</student>
</students><!--节点的结束标签都是以/加标签名称组成 -->
其中相关节点等知识不在详述,自行查阅。
首先,我们用dom的方式进行解析:
//dom解析XML文件
-(void)domParser{
    //获得文件路径
    NSString* path = [[NSBundle mainBundle]pathForResource:@"XMLDemo" ofType:@"xml"];
    
    //见文件转化为data类型
    NSData* XMLData = [NSData dataWithContentsOfFile:path];
    
    //将文件类型,通过note对象,转化为树形结构(一次性从内存中将xml文件转化为倒着的树形结构),在这里意味着将文件内容已经拉入了项目空间进行操作。
    GDataXMLDocument *doc = [[GDataXMLDocument alloc]initWithData:XMLData options:0 error:nil];
    //得到根节点
    GDataXMLElement *rootElement = [doc rootElement];
    //得到根节点的所有以“student”命名的子节点
    NSArray* stuArr = [rootElement elementsForName:@"student"];
    
    //初始化可变数组,用来存放学生的信息(需要注意的是,这里必须了解xml文件的数据结构,确定节点的末尾)
    NSMutableArray* stumArr = [NSMutableArray array];
    //得到所有Student节点的所有子节点,即Student对象中具体的个人
    for (GDataXMLElement* itemElement in stuArr) {
        NSArray* nameElement = [itemElement elementsForName:@"name"];
        //从节点中取值
        NSString *nameStr = [[nameElement objectAtIndex:0] stringValue];
        NSArray* sexArr = [itemElement elementsForName:@"sex"];
        NSString *sexStr = [[sexArr objectAtIndex:0] stringValue];
        
        NSArray *ageArr = [itemElement elementsForName:@"age"];
        NSString *ageStr = [[ageArr objectAtIndex:0] stringValue];
        
        NSDictionary *dic = [[NSDictionary alloc]initWithObjectsAndKeys:nameStr,@"name",sexStr,@"sex",ageStr,@"age", nil];
        [stumArr addObject:dic];
    }
    NSLog(@"%@",stumArr);
}

然后看看sax解析的方式:
//xml的sax解析
-(void)saxParser{
    
    //获得文件路径
    NSString* pathStr = [[NSBundle mainBundle] pathForResource:@"XMLDemo" ofType:@"xml"];
    //转化为data文件
    NSData* data = [NSData dataWithContentsOfFile:pathStr];
    //sax解析
    NSXMLParser* parser= [[NSXMLParser alloc] initWithData:data];
    //指定代理,并导入协议,在sax解析的方式里,是通过逐行解析的方式去解析xml文件,在dialing方法中分步执行
    [parser setDelegate:self];
    //开始解析(同步,意思是解析不完成,下面的代码就不会执行)
    BOOL isSuccessful = [parser parse];
    if (isSuccessful) {
        NSLog(@"解析成功");
    }else{
        NSLog(@"解析失败");
    }
    
}

#pragma mark <NSXMLParserDelegate>
//开始解析
-(void)parserDidStartDocument:(NSXMLParser *)parser{
    
    NSLog(@"开始解析%s",__FUNCTION__);
    //初始化一个最大的容器
    self.allStudentMArr = [NSMutableArray array];
}
//开始解析节点
/**
 *  Description
 *
 *  @param parser        解析对象
 *  @param elementName   标签名称
 *  @param namespaceURI  命名空间指向的链接
 *  @param qName         命名空间的名称
 *  @param attributeDict 节点的属性
 */
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict{
    NSLog(@"开始解析节点%s",__FUNCTION__);
    if ([elementName isEqualToString:@"student"]) {
        //当解析到Student的时候,说明已经到了获取该节点的子节点的时候了,所以应该初始化容器了
        self.singleStudentMDic = [NSMutableDictionary dictionary];
    }
}

//开始取值
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
    
    NSLog(@"取值%s",__FUNCTION__);
    if (self.noteValueString) {
//        [self.noteValueString appendString:string];
        NSString* str = [self.noteValueString stringByAppendingString:string];
//        self.noteValueString = [str mutableCopy];
        self.noteValueString = [NSMutableString stringWithString:str];
    }else{
        self.noteValueString = [NSMutableString stringWithString:string];
    }
    
}
//解析完毕某个节点
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
    
    if ([elementName isEqualToString:@"name"]) {
        [self.singleStudentMDic setObject: [self replaceStringWithString:self.noteValueString] forKey:elementName];
    }
    //每次解析玩一个节点,我们都需要将可变字符串清理一次,因为可变字符串是多次使用的
    if ([elementName isEqualToString:@"sex"]) {
        [self.singleStudentMDic setObject: [self replaceStringWithString:self.noteValueString] forKey:elementName];
    }
    if ([elementName isEqualToString:@"age"]) {
        [self.singleStudentMDic setObject: [self replaceStringWithString:self.noteValueString] forKey:elementName];
    }
    if ([elementName isEqualToString:@"student"]) {
        [self.allStudentMArr addObject:self.singleStudentMDic];
    }
    //每次对解析完毕的节点,必须将存储字符串置空。
    self.noteValueString = nil;
}

//解析完毕
-(void)parserDidEndDocument:(NSXMLParser *)parser{
    NSLog(@"%s",__FUNCTION__);
    
    NSLog(@"%@",self.allStudentMArr);
}
//自定义的方法
-(NSString*)replaceStringWithString:(NSMutableString*)sourceString{
    //剔除字符串中的空格、换行、制表符
    NSString* resultString = [sourceString stringByReplacingOccurrencesOfString:@"\n" withString:@"" ];
    resultString = [resultString stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    resultString = [resultString stringByReplacingOccurrencesOfString:@"\t" withString:@""];
    resultString = [resultString stringByReplacingOccurrencesOfString:@" " withString:@""];
    return resultString;
}

同时注意:sax解析和dom解析时都需要导入第三方文件
包括json解析也需要进行该操作:
在引入第三方文件时,一般会遇到一些问题。

问题一:部分头文件报错

解决办法:

在工程的设置界面,设置文件路径:



问题二:导入文件报错

解决办法:

如果是因为内存管理方式的报错,那么在ARC模式下添加MRC模式就可以了。



同样,dom解析还有另一个功能,是可以创建xml节点。
demo如下:
//通过dom解析的方式,为xml增加节点(sax解析只可以读取,不可添加)
-(void)domAddNote{
    //获得文件路径
    NSString* path = [[NSBundle mainBundle]pathForResource:@"XMLDemo" ofType:@"xml"];
    
    //见文件转化为data类型
    NSData* XMLData = [NSData dataWithContentsOfFile:path];
    
    //将文件类型,通过note对象,转化为树形结构(一次性从内存中将xml文件转化为倒着的树形结构)
    GDataXMLDocument *doc = [[GDataXMLDocument alloc]initWithData:XMLData options:0 error:nil];
    //得到根节点
    GDataXMLElement *rootElement = [doc rootElement];
    //创建一个我们需要添加的节点(Student)
    GDataXMLElement *creatElement = [GDataXMLNode elementWithName:@"student"];
    GDataXMLElement* nameElement = [GDataXMLElement elementWithName:@"name" stringValue:@"金鹏"];
    [creatElement addChild:nameElement];
    GDataXMLElement* ageElement = [GDataXMLElement elementWithName:@"age" stringValue:@"99"];
    [creatElement addChild:ageElement];
    GDataXMLElement* sexElement = [GDataXMLElement elementWithName:@"sex" stringValue:@"男男女女"];
    [creatElement addChild:sexElement];
    
    [rootElement addChild:creatElement];
    
    //得到根节点的所有子节点
    NSArray* stuArr = [rootElement elementsForName:@"student"];
    
    //初始化可变数组,用来存放学生的信息
    NSMutableArray* stumArr = [NSMutableArray array];
    //得到所有Student节点的所有子节点,即Student对象中具体的个人
    for (GDataXMLElement* itemElement in stuArr) {
        NSArray* nameElement = [itemElement elementsForName:@"name"];
        NSString *nameStr = [[nameElement objectAtIndex:0] stringValue];
        NSArray* sexArr = [itemElement elementsForName:@"sex"];
        NSString *sexStr = [[sexArr objectAtIndex:0] stringValue];
        
        NSArray *ageArr = [itemElement elementsForName:@"age"];
        NSString *ageStr = [[ageArr objectAtIndex:0] stringValue];
        
        NSDictionary *dic = [[NSDictionary alloc]initWithObjectsAndKeys:nameStr,@"name",sexStr,@"sex",ageStr,@"age", nil];
        [stumArr addObject:dic];
    }
    NSLog(@"%@",stumArr);


}

三、json数据结构与解析

json数据示例:
{
    "reason":"success",
    "result":[
        {
            "movieId":"216609",
            "movieName":"诡八楼",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583083"
        },
        {
            "movieId":"216391",
            "movieName":"摩登森林之美食总动员",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583246"
        },
        {
            "movieId":"216162",
            "movieName":"龟兔再跑",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583181"
        },
        {
            "movieId":"215977",
            "movieName":"森林孤影",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583247"
        },
        {
            "movieId":"215874",
            "movieName":"从哪来,到哪去",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583542"
        },
        {
            "movieId":"215823",
            "movieName":"有一天",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583092"
        },
        {
            "movieId":"215372",
            "movieName":"兰辉",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583163"
        },
        {
            "movieId":"215365",
            "movieName":"我是你的野蛮女友",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583708"
        },
        {
            "movieId":"215115",
            "movieName":"触不可及",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583077"
        },
        {
            "movieId":"212024",
            "movieName":"死亡派对",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583084"
        },
        {
            "movieId":"210860",
            "movieName":"女生宿舍",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583157"
        },
        {
            "movieId":"209708",
            "movieName":"不惧风暴",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583080"
        },
        {
            "movieId":"206446",
            "movieName":"黎明之眼",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583098"
        },
        {
            "movieId":"205991",
            "movieName":"一生一世",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583079"
        },
        {
            "movieId":"205238",
            "movieName":"缘来是游戏",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583162"
        },
        {
            "movieId":"190893",
            "movieName":"美女与野兽",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583090"
        },
        {
            "movieId":"190537",
            "movieName":"敢死队3",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583082"
        },
        {
            "movieId":"183090",
            "movieName":"空中营救",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583076"
        },
        {
            "movieId":"181874",
            "movieName":"动物也疯狂",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583243"
        },
        {
            "movieId":"179197",
            "movieName":"绝密跟踪",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583081"
        },
        {
            "movieId":"174132",
            "movieName":"分歧者:异类觉醒",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583102"
        },
        {
            "movieId":"169864",
            "movieName":"猩球崛起:黎明之战",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583078"
        },
        {
            "movieId":"128888",
            "movieName":"挑战者联盟",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583248"
        },
        {
            "movieId":"49362",
            "movieName":"共和国之旗",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583541"
        },
        {
            "movieId":"42201",
            "movieName":"红旗谱",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583536"
        },
        {
            "movieId":"28678",
            "movieName":"原色深海",
            "pic_url":"http:\/\/v.juhe.cn\/movie\/picurl?2583539"
        }
    ],
    "error_code":0
}


解析demo:
//JSON解析
-(void)jsonData{
    //先得到json文件的路径
    NSString* path = [[NSBundle mainBundle]pathForResource:@"MovieList" ofType:@"txt"];
    //将数据类型转化为nsdata类型
    NSData *data = [NSData dataWithContentsOfFile:path];
    NSString *dataString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"%@",dataString);
    //解析
    NSError *error;
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
    NSLog(@"%@",dic);
}

当json数据串不是标准的数据文件时,需要对转化为的string进行剪切操作,从而进行工作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值