美文网首页
05、网络解析

05、网络解析

作者: 深爱久随i | 来源:发表于2016-12-20 20:19 被阅读0次

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

    XML解析

    XMl事例:

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 根结点 是所有节点的父节点或者爷节点 -->
    <students> <!--开始节点-->
    <!--student的子节点,position就是该节点的属性-->
       <student position="愤青">
         <!--lyj是name节点的内容,我们可以将该节点所有的特性都用属性来表示,但是为了阅读起来方便,我们一般也会将该节点的特性用他的子节点来表示-->
         <name>lyj</name>
         <age>25</age>
         <sex>男</sex>
       </student>
       <student>
         <name>zza</name>
         <age>22</age>
         <sex>保密</sex>
       </student>
    </students> <!--结束节点-->
    

    XML有两种解析方法:DOM(Document Object Model)解析和SAX(Simple API for XML)工具

    1.SAX解析

    SAX基本原理:采用事件驱动解析XML文件,以流式方式逐行的去读,它不需要解析完整个文档,在按内容顺序解析文档的过各中,SAX会判断当前讲到的字符是否合法XML语法中的某部分,如果符合就触发事件(例如startDocument()、endDocument()诸如此类的事件),它的特点是不会记录前面所碰到的标签,并且它是一个解析速度快并且占用内存少的XML解析器
    特点:
    一.是基于事件驱动的解析方式
    二.逐行解析
    三.只能读取(DOM解析可读可写)
    四.一般只用做文档比较大的时候

    //sax解析
    -(void)saxPath{
        //sax解析:基于事件驱动的解析方式,逐行解析
        NSString* xmlPath=[[NSBundle mainBundle] pathForResource:@"xml" ofType:@"xml"];
        NSString* xmlStr=[NSString stringWithContentsOfFile:xmlPath encoding:NSUTF8StringEncoding error:nil];
        //字符串转data类型
        NSData* xmlData=[xmlStr dataUsingEncoding:NSUTF8StringEncoding];
        //参数:需要解析的文件内容
        NSXMLParser* xmlParser=[[NSXMLParser alloc] initWithData:xmlData];
        //设置代理
        xmlParser.delegate=self;
        //开始解析  同步的过程  当整个解析完成了才会执行下一行代码
        BOOL isSuccess=[xmlParser parse];
        if (isSuccess) {
            NSLog(@"解析成功");
        }else{
            NSLog(@"解析失败");
        }
        //解析的过程不结束,就不会执行该打印
        NSLog(@"我在解析的最底下");
      
    }
    

    下来遵循协议,实现协议方法,为了方便获取数据,声明一个字典和数组

    @interface ViewController ()<NSXMLParserDelegate>
    @property(nonatomic,strong)NSMutableArray* allDataArray;//存放所有student的节点
    @property(nonatomic,strong)NSMutableDictionary* studentDic;//将student转换为字典
    @property(nonatomic,strong)NSString* noteValueString;//存储节点中的值
    
    #pragma mark--------parser解析的代理方法
    //开始解析整个文档了
    -(void)parserDidStartDocument:(NSXMLParser *)parser{
            NSLog(@"开始解析整个文档了");
        //初始化外部的可变数组,准备存放student节点
        self.allDataArray=[[NSMutableArray alloc] init]; 
        }
    //当碰到开始节点或开始标签的时候会执行的代理方法
    //elementName:标签名称(节点名),例如<name>
    //namespaceURI:命名空间的标识名 例如<teacher xmlns:l="www.lanou3g.com">
    //qName:命名空间的值,就是上面的 www.lanou3g.com
    //attributeDict:标签的属性 例如 <student position="愤青"> position就是标签的属性,attributeDict=={pasition:"愤青"}
    -(void)parser:(NSXMLParser*)parser didStartElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName attributes:(nonnull NSDictionary<NSString *,NSString *> *)attributeDict{
        NSLog(@"碰到开始标签----%@",elementName);
        //当开始解析student节点的时候,说明我们要用到字典了,就需要对字典进行初始化
        if ([elementName isEqualToString:@"student"]) {
            self.studentDic=[[NSMutableDictionary alloc] init];
        }
        
    }
        
    //取出标签中的值
    //string:就是标签中的值
    -(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
        NSLog(@"正在解析的值为---%@",string);
        //将节点的内容存储起来,以供节点解析结束使用
        self.noteValueString=string;
        
    }
        
    //遇到当前正在解析标签结束标签
    -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
        NSLog(@"碰到结束标签----%@",elementName);
        if ([elementName isEqualToString:@"name"]) {
            //说明name标签解析结束
            [self.studentDic setObject:self.noteValueString forKey:elementName];
        }
        
        if ([elementName isEqualToString:@"age"]) {
            //说明age标签解析结束
            [self.studentDic setObject:self.noteValueString forKey:elementName];
        }
        if ([elementName isEqualToString:@"sex"]) {
            //说明sex标签解析结束
            [self.studentDic setObject:self.noteValueString forKey:elementName];
        }
        if ([elementName isEqualToString:@"student"]) {
            //说明一个student已经解析完成,说明一个字典已经完整,应该将字典放入数组中了
            [self.allDataArray addObject:self.studentDic];
        }
    }
        
    //整个文档解析结束
    -(void)parserDidEndDocument:(NSXMLParser *)parser{
            NSLog(@"整个文档解析结束");
        //当整个文档解析结束,说明所有的数据我们已经拿到,可以正常使用了
        NSLog(@"----%@",self.allDataArray);
      }
    
    //当解析出错会调用的方法
    -(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{
        NSLog(@"解析出现错误---%@",parseError.description);
    }
        
    
    2.DOM解析

    dom解析基于文档驱动的解析方式,DOM解析XML时,读入整个XML文档并构建一个驻留内存的树结构(节点树),通过遍历树结构可以检索任意XML节点,读取他的属性和值,而且通常情况下,可以借助XPath,直接查询XML节点


    使用方法:
    1.获取GDataXMLNode.h/m文件,将GDataXMLNode.h/m文件添加到工程中
    2.向工程中增加“libxml2.dylib”动态库
    具体做法 选中整个工程 在Build Phases的倒数第二个选项中点“+”号,搜索libxml2.dylib 并添加
    3.在工程的“Build Settings”页中找到“Header Search Path” 点击添加 "/usr/include/libxml2"
    4.导入“GDataXMLNode.h”文件到头文件 如果工程能编译通过,说明添加成功
    注意:
    (1)在工程的Build phases设置的Link Binary With Libraries里面点击加号,搜索libxml2.tbd,选择添加

    11111.png

    (2)在工程的Build Settings设置里面搜索search,找到Search paths选项下的Header Search Paths,加入一条/usr/include/libxml2这里三个反斜杠不能少

    222.png

    (3)在工程的Build Settings设置里面搜索Other Linker Flags,找到Other Linker Flags,双击空白处输入-lxml2


    3333.png

    这样在编译就不会报错啦。☺️

    //dom解析  基于文档驱动的解析方式
    -(void)domParser{
        //需要获取解析的源文件
        NSString* xmlPath=[[NSBundle mainBundle] pathForResource:@"xml" ofType:@"xml"];
        NSString* xmlStr=[NSString stringWithContentsOfFile:xmlPath encoding:NSUTF8StringEncoding error:nil];
        //字符串转data类型
        NSData* xmlData=[xmlStr dataUsingEncoding:NSUTF8StringEncoding];
       //dom解析
        //step1:将源xml文件转换成树状结构的文档放在内存中,以供遍历获取每个节点
        GDataXMLDocument* xmlDoc=[[GDataXMLDocument alloc] initWithData:xmlData encoding:NSUTF8StringEncoding error:nil];
        //step2:获取根节点 就相当于获取到了students节点
        GDataXMLElement* rootElement=[xmlDoc rootElement];
        //step3:获取我们需要的子节点
        //参数:我们需要获取的标签名
    //    NSArray* studentArray=[rootElement elementsForName:@"student"];
        //初始化一个可变数组,准备存放所有的student转换成的字典
        NSMutableArray* allStudentsArray=[[NSMutableArray alloc] init];
        
        //添加节点(向现有的文档动态的增加一个student节点)
        //节点创建   <student></student>
        GDataXMLElement* studentElement = [GDataXMLElement elementWithName:@"student"];
        //将student节点加入到它的父节点中
    //    [rootElement addChild:studentElement];
        //为student增加子节点
        GDataXMLElement* nameElement = [GDataXMLElement elementWithName:@"name" stringValue:@"ze an"];
        GDataXMLElement* ageElement = [GDataXMLElement elementWithName:@"age" stringValue:@"23"];
        GDataXMLElement* genderElement = [GDataXMLElement elementWithName:@"gender" stringValue:@"未知"];
        [studentElement addChild:nameElement];
        [studentElement addChild:ageElement];
        [studentElement addChild:genderElement];
         [rootElement addChild:studentElement];
         NSArray* studentArray=[rootElement elementsForName:@"student"];
       
    
        
        //step4:遍历数组
        //stuNode:对应一个student节点
    /*<student>
        <name></name>
        <age></age>
        <sex></sex>
    </student>
        */
        
        //每执行一次循环体,就相当于获取了一个完整的student节点,结构如上
    //    for (GDataXMLElement* stuelement in studentArray) {
    //        //初始化一个字典
    //      NSMutableDictionary* studentDic=[[NSMutableDictionary alloc] init];
    ////        NSString* name=[[[stuelement elementsForName:@"name"] firstObject] stringValue];
    //        //获取name节点
    //        GDataXMLElement* nameElement=[stuelement elementsForName:@"name"].firstObject;
    //        //取出节点中的值
    //        NSString* name=[nameElement stringValue];
    //        //将name的值放入字典中
    //        [studentDic setObject:name forKey:@"name"];
    //        
    //        //获取age节点
    //        GDataXMLElement* ageElement=[stuelement elementsForName:@"age"].firstObject;
    //        NSString* age=[ageElement stringValue];
    //        [studentDic setObject:age forKey:@"age"];
    //        
    //        //获取sex节点
    //        GDataXMLElement* sexElement=[stuelement elementsForName:@"sex"].firstObject;
    //        NSString* sex=[sexElement stringValue];
    //        [studentDic setObject:sex forKey:@"sex"];
    //        //将字典放入数组中
    //        [allStudentsArray addObject:studentDic];
    //    }
    //    NSLog(@"----%@",allStudentsArray);
        
       
        for (GDataXMLElement* studentNode in studentArray) {
            //遍历获取student所有的子节点
            NSArray* subStudentNode=[studentNode children];
             NSMutableDictionary* studentDic=[[NSMutableDictionary alloc] init];
            for (GDataXMLElement* subOfStudentNode in subStudentNode) {
                //获取子节点的名称
                NSString* noteName=[subOfStudentNode name];
                //获取节点内容
                NSString* noteValue=[subOfStudentNode stringValue];
                [studentDic setObject:noteValue forKey:noteName];
               
            }
            //  将字典加入到数组中
             [allStudentsArray addObject:studentDic];
        }
        NSLog(@"----%@",allStudentsArray);
        
        
    }
    
    3.JSON解析
    //json解析
    -(void)jsonParser{
        //获取要解析的json源文件
        NSString* jsonPath=[[NSBundle mainBundle] pathForResource:@"DemoJson" ofType:@"json"];
        NSString* jsonStr=[NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil];
        //字符串转data类型
        NSData* jsonData=[jsonStr dataUsingEncoding:NSUTF8StringEncoding];
        //json解析
       NSDictionary* dic= [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:nil];
        NSLog(@"---%@",dic);
        
    }
        
    

    相关文章

      网友评论

          本文标题:05、网络解析

          本文链接:https://www.haomeiwen.com/subject/mdjfvttx.html