zoukankan      html  css  js  c++  java
  • iOS网络编程解析协议二:XML数据传输解析

    XML两种解析方式,一种是SAX,NSXMLParser是SAX方法解析,另一种是DOM(Document Object Model);

    区别:

    SAX:

    只能读,不能修改,只能顺序访问,适合解析大型XML,解析速度快
    常应用于处理大量数据的XML,实现异构系统的数据访问,实现跨平台
    从文档的开始通过每一节点移动,定位一个特定的节点

    DOM:

    不仅能读,还能修改,而且能够实现随机访问,缺点是解析速度慢,适合解析小型文档
    一般应用与小型的配置XML,方便操作
    为载入到内存的文档节点建立类型描述,呈现可横向移动、潜在巨大的树型结构
    在内存中生成节点树操作代价昂贵
     
    这里我们主要介绍使用SAX方式,NSXMLParser是SAX的方法解析,NSXMLParser解析通过NSXMLParserDelegate协议代理方法来完成,解析过程如下:
    NSXMLParser解析过程:
    <1>. 创建NSXMLParser实例,并传入从服务器接收的XML数据
    <2>. 定义解析器代理
    <3>. 解析器解析
    <4.. 通过解析代理方法完成XML数据的解析
     
    举例一:把本机服务器上的student.xml文件中数据解析并输出到控制台上。
    文件和内容截图截图如下:
          
     
    具体代码如下:
    //创建一个学生Student类,并声明属性:姓名name、年龄age、性别sex
    1 #import <Foundation/Foundation.h>
    2 
    3 @interface Student : NSObject
    4 @property (copy,nonatomic)NSString *name;
    5 @property (assign,nonatomic)NSInteger age;
    6 @property (assign,nonatomic)char sex;
    7 @end

    //重写输出方法

     1 #import "Student.h"
     2 
     3 @implementation Student
     4 
     5 //重写输出方式
     6 -(NSString*)description
     7 {
     8     return [NSString stringWithFormat:@"name:%@,age:%ld,sex:%c",_name,_age,_sex];
     9 }
    10 
    11 @end

    //在ViewController类中带入头文件和设置相关的属性信息,同时实现解析协议<NSXMLParserDelegate>

    1 #import "ViewController.h"
    2 #import "Student.h"
    3 
    4 @interface ViewController ()<NSXMLParserDelegate>
    5 @property (strong,nonatomic)NSMutableArray *stus;           //存储解析到的学生对象
    6 @property (strong,nonatomic)Student *currentStudent;        //解析到的当前学生对象
    7 @property (strong,nonatomic)NSMutableString *elementValue;  //节点值
    8 
    9 @end

    //下载数据并进行解析

     1 - (void)viewDidLoad
     2 {
     3     [super viewDidLoad];
     4     
     5     //1.从网络下载数据
     6     NSURL *URL = [NSURL URLWithString:@"http://localhost/userManager/student.xml"];
     7     NSData *data = [NSData dataWithContentsOfURL:URL];
     8     
     9     //2.创建解析对象
    10     NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data];
    11     
    12     //3.设置解析对象的代理
    13     parser.delegate = self;
    14     
    15     //4.开始解析
    16     [parser parse];
    17 }

    //实现代理的解析方法

    #pragma mark -<NSXMLParserDelegate>

    //文档开始
    1 //文档开始
    2 -(void)parserDidStartDocument:(NSXMLParser *)parser
    3 {
    4     //初始化数组
    5     self.stus = [NSMutableArray array];
    6 }
     
    //文档结束
    1 //文档结束
    2 -(void)parserDidEndDocument:(NSXMLParser *)parser
    3 {
    4     //输出解析后得到的数据
    5     [self.stus enumerateObjectsUsingBlock:^(Student *student, NSUInteger idx, BOOL *stop) {
    6         NSLog(@"%@",student);
    7     }];
    8 }
     
    //元素开始
     1 //元素开始
     2 -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
     3 {
     4     //创建学生对象
     5     if([elementName isEqualToString:@"student"])
     6     {
     7         self.currentStudent = [[Student alloc]init];
     8     }
     9     
    10     //初始化节点值
    11     else if ([elementName isEqualToString:@"name"] ||
    12              [elementName isEqualToString:@"age"]  ||
    13              [elementName isEqualToString:@"sex"]   )
    14     {
    15         self.elementValue = [[NSMutableString alloc]init];
    16     }
    17 }
    //找到文字
    1 //找到文字
    2 -(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
    3 {
    4     //获取节点值
    5     [self.elementValue appendString:string];
    6 }
    //元素结束
     1 //元素结束
     2 -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
     3 {
     4     //解析得到学生对象姓名
     5     if([elementName isEqualToString:@"name"])
     6     {
     7         self.currentStudent.name = self.elementValue;
     8     }
     9     
    10     //解析得到学生对象年龄
    11     else if([elementName isEqualToString:@"age"])
    12     {
    13         self.currentStudent.age = [self.elementValue integerValue];
    14     }
    15     
    16     //解析得到学生对象性别
    17     else if([elementName isEqualToString:@"sex"])
    18     {
    19         self.currentStudent.sex = [self.elementValue characterAtIndex:0];
    20     }
    21     
    22     //将学生对象添加到数组中
    23     else if ([elementName isEqualToString:@"student"])
    24     {
    25         [self.stus addObject:self.currentStudent];
    26     }
    27 }
    //解析出错
    1 //解析出错
    2 -(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
    3 {
    4     NSLog(@"解析出错:%@",parseError);
    5 }

    输出结果如下:

    2015-09-24 19:08:34.377 XMLParser解析student.xml[3566:218809] name:kellen,age:25,sex:M
    2015-09-24 19:08:34.378 XMLParser解析student.xml[3566:218809] name:jack,age:35,sex:M

    举例二:把本机服务器上的cities.xml文件中数据解析并输出到控制台上,这个比较复杂一些。

    文件截图和部分内容截图(内容太多,不便全部截图)如下

      

    具体代码如下:都在ViewController类中写代码

    //实现协议<NSXMLParserDelegate>并声明必要的属性

    1 #import "ViewController.h"
    2 
    3 @interface ViewController ()<NSXMLParserDelegate>
    4 @property (strong,nonatomic)NSMutableDictionary *province; //存储所有的省份
    5 @property (strong,nonatomic)NSMutableDictionary *city;     //存放对应省份的所有城市
    6 @property (strong,nonatomic)NSMutableString *keyName;      //字典的键名
    7 @property (strong,nonatomic)NSMutableString *elementValue; //节点的值
    8 @property (strong,nonatomic)NSMutableArray *arrayTemp;     //临时数组,存放省名或城市名
    9 @end

    //下载数据并进行解析

     1 - (void)viewDidLoad
     2 {
     3     [super viewDidLoad];
     4     
     5     //1.从网络下载数据
     6     NSURL *URL = [NSURL URLWithString:@"http://localhost/userManager/cities.xml"];
     7     NSData *data = [NSData dataWithContentsOfURL:URL];
     8     
     9     //2.创建解析对象
    10     NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data];
    11     
    12     //3.设置解析对象的代理
    13     parser.delegate = self;
    14     
    15     //4.开始解析
    16     [parser parse];
    17 }

    //实现解析代理的方法

    #pragma mark -<NSXMLParserDelegate>

    文档开始

    1 //文档开始
    2 -(void)parserDidStartDocument:(NSXMLParser *)parser
    3 {
    4     //初始化省份字典
    5     self.province = [NSMutableDictionary dictionary];
    6 }

    文档结束

    1 //文档结束
    2 -(void)parserDidEndDocument:(NSXMLParser *)parser
    3 {
    4     //输出所有的城市
    5     [self.province setObject:self.city forKey:@"cities"];
    6     NSLog(@"%@",self.province);
    7 }

    元素开始

     1 //元素开始
     2 -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
     3 {
     4     //初始化临时数组
     5     if([elementName hasPrefix:@"array"])
     6     {
     7         self.arrayTemp = [NSMutableArray array];
     8     }
     9     
    10     //初始化节点值
    11     else if ([elementName hasPrefix:@"key"] || [elementName hasPrefix:@"string"])
    12     {
    13         self.elementValue = [[NSMutableString alloc]init];
    14     }
    15     
    16     //初始化城市字典
    17     else if ([elementName hasPrefix:@"dict"])
    18     {
    19         if ([self.keyName hasPrefix:@"cities"])
    20         {
    21             self.city = [NSMutableDictionary dictionary];
    22         }
    23     }
    24 }

    找到文字

    1 //找到文字
    2 -(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
    3 {
    4     [self.elementValue appendString:string];
    5 }

    元素结束

     1 //元素结束
     2 -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
     3 {
     4         //取节点值
     5         if([elementName hasPrefix:@"key"])
     6         {
     7             self.keyName = self.elementValue;
     8         }
     9     
    10         //将省份或城市添加到临时数组
    11         else if ([elementName hasPrefix:@"string"])
    12         {
    13             [self.arrayTemp addObject:self.elementValue];
    14         }
    15     
    16         //将临时数组添加到字典中
    17         else if([elementName hasPrefix:@"array"])
    18         {
    19             if([self.keyName hasPrefix:@"provinces"])
    20             {
    21                 [self.province setObject:self.arrayTemp forKey:self.keyName];
    22             }
    23             else
    24             {
    25                 [self.city setObject:self.arrayTemp forKey:self.keyName];
    26             }
    27         }
    28 }

    解析出错

    1 //解析出错
    2 -(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
    3 {
    4     NSLog(@"解析出错:%@",parseError);
    5 }

    运行结果如下:(由于编码的不同,无法显示汉字,但是结果是正确的,同样内容太多,只给出部分结果)

    2015-09-24 19:50:35.139 XMLParse解析cities.xml[3800:240028] {
        cities =     {
            "U4e0aU6d77
    		
    			" =         (
                "U4e0aU6d77
    		
    		"
            );
            "U4e91U5357
    		
    			" =         (
                "U6606U660e
    			",
                "U4fddU5c71
    			",
                "U695aU96c4
    			",
                "U5927U7406
    			",
                "U5fb7U5b8f
    			",
                "U8feaU5e86
    			",
                "U4e2aU65e7
    			",
                "U4e3dU6c5f
    			",
                "U4e34U6ca7
    			",
                "U6012U6c5f
    			",
                "U66f2U9756
    			",
                "U601dU8305
    			",
                "U6587U5c71
    			",
                "U897fU53ccU7248U7eb3
    			",
                "U7389U6eaa
    			",
                "U662dU901a
    		
    		"
            );
            "U5185U8499U53e4
    		
    			" =         (
                "U547cU548cU6d69U7279
    			",
                "U963fU62c9U5584U76df
    			",
                "U5df4U5f66U6dd6U5c14U76df
    			",
                "U5305U5934
    			",
                "U8d64U5cf0
    			",
                "U9102U5c14U591aU65af
    			",
                "U547cU4f26U8d1dU5c14
    			",
                "U901aU8fbd
    			",
                "U4e4cU6d77
    			",
                "U4e4cU5170U5bdfU5e03U76df
    			",
                "U9521U6797U90edU52d2U76df
    			",
    ......................................
    ......................................
  • 相关阅读:
    react 使用 redux 的时候 用 ref获取子组件的state
    node-rsa 非对称加密和解密
    electron 前端开发桌面应用
    react-router v4 使用 history 控制路由跳转
    react 写一个贪吃蛇
    【Java并发编程】:并发新特性—塞队列和阻塞栈
    【Java并发编程】:并发新特性—Executor框架与线程池
    【Java并发编程】:深入Java内存模型—内存操作规则总结
    【Java并发编程】:深入Java内存模型——happen-before规则及其对DCL的分析
    【Java并发编程】:加锁和volatile变量
  • 原文地址:https://www.cnblogs.com/XYQ-208910/p/4836354.html
Copyright © 2011-2022 走看看