欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS之数据解析之XML解析详解

程序员文章站 2024-02-16 10:00:52
xml解析常见的两种方式:dom解析和sax解析 dom解析 dom:document object model(文档对象类型).解析xml时,读入整个xm...

xml解析常见的两种方式:dom解析和sax解析

dom解析

  • dom:document object model(文档对象类型).解析xml时,读入整个xml文档并构建一个驻留内存的树结构(节点树),通过遍历数结构可以检索任意xml节点,读取它的属性和值,而且通常情况下,可以借助xpath,直接查询xml节点.
  • 进行dom方式解析数据需要使用一个第三方的类gdataxmlnode
  • gdataxmlnode是google提供的开源xml解析类,对libxml2.tbd进行了objective-c的封装,能对较小或者中等的xml文档进行读写操作且支持xpath语法.
  • gdataxmlnode使用方法:

1 获取gdataxmlnode.h/m文件,将gdataxmlnode.h/m文件添加到工程中.

2 向工程中添加'libxml2.tbd'动态库.

3 在工程的”build settings”页中找到”header search path”项,添加”/usr/include/libxml2”.

4 导入”gdataxmlnode.h”文件到头文件中,如工程能编译通过,则说明gdataxmlnode添加成功. 

(gdataxmlnode第三方可在github搜索下载)

解析代码如下:

-(void)xmldommethed{

  //盛放所有的字典
 self.sourcearray = [nsmutablearray array];
  //setp1.得到需要解析的数据
  nsstring *xmlpath = [[nsbundle mainbundle] pathforresource:@"xmldemo" oftype:@"xml"];
  //step2.转换为nsdata类型
  nsdata *xmldata = [nsdata datawithcontentsoffile:xmlpath];
  //step3.1 构建document文档对象(options预留参数)
  gdataxmldocument *doc = [[gdataxmldocument alloc] initwithdata:xmldata options:0 error:nil];
  //step3.2 找到根节点(students)
  gdataxmlelement *rootelement = [doc rootelement];
 //step3.3 找到根节点的所有子节点
  nsarray *allsubnotes = [rootelement elementsforname:@"student"];
  //step3.3 找到student节点的所有子节点
  for (gdataxmlelement *item in allsubnotes) {

    //每次循环开始的时候,说明是一个新的student节点,我们需要字典来盛放它所有的值
    nsmutabledictionary *studentdic = [nsmutabledictionary dictionary];
    //得到name节点
    nsarray *namearray = [item elementsforname:@"name"];
    gdataxmlelement *nameelement = [namearray objectatindex:0];
    nsstring *name = [nameelement stringvalue];
    [studentdic setobject:name forkey:@"name"];

    //取出age
    nsarray *agearray = [item elementsforname:@"age"];
    gdataxmlelement *ageelement = [agearray objectatindex:0];
    nsstring *age = [ageelement stringvalue];
    [studentdic setobject:age forkey:@"age"];

    //取出sex
    nsarray *sexarray = [item elementsforname:@"sex"];
    gdataxmlelement *sexelement = [sexarray objectatindex:0];
    nsstring *sex = [sexelement stringvalue];
    [studentdic setobject:sex forkey:@"sex"];
    //把student字典添加到数组中
    [self.sourcearray addobject:studentdic];
  }
nslog(@"%@",self.sourcearray);
 }

写入代码如下:

//通过dom解析方式为xml增加节点 (sax只可以读取,不可以添加)
- (void)domaddnote{
  //获得文件路径
  nsstring *xmlpath = [[nsbundle mainbundle] pathforresource:@"xmldemo" oftype:@"xml"];
  //将文件转换为data类型
  nsdata *xmldata = [nsdata datawithcontentsoffile:xmlpath];

  gdataxmldocument *doc = [[gdataxmldocument alloc] initwithdata:xmldata options:0 error:nil];
  gdataxmlelement *rootelement = [doc rootelement];
  //创建一个我们需要添加的节点(student)
  gdataxmlelement *createelement = [gdataxmlelement elementwithname:@"student"];
  //为student节点添加属性
  [createelement addattribute:[gdataxmlelement attributewithname:@"attribute" stringvalue:@"aa"]];
  //为student节点添加子节点
  gdataxmlelement *namenode = [gdataxmlelement elementwithname:@"name" stringvalue:@"美丽"];
  [createelement addchild:namenode];
  gdataxmlelement *agenode = [gdataxmlelement elementwithname:@"age" stringvalue:@"18"];
  [createelement addchild:agenode];
  gdataxmlelement *sexnode = [gdataxmlelement elementwithname:@"sex" stringvalue:@"男"];
  [createelement addchild:sexnode];

  //将创建好的student节点,添加到根节点,也就是students节点下
  [rootelement addchild:createelement];

  //得到所有的student节点
  nsarray *stuelementarray = [rootelement elementsforname:@"student"];

  //遍历得到每个student节点,以便获得student的子节点的值。
  for (gdataxmlelement* item in stuelementarray) {

    //获得student节点的attribute属性值
    nslog(@"%@",[[item attributeforname:@"attribute"] stringvalue]);

    nsarray *namearray = [item elementsforname:@"name"];
    gdataxmlelement *nameelement = [namearray objectatindex:0];
    nsstring *name = [nameelement stringvalue];

    //取出age
    nsarray *agearray = [item elementsforname:@"age"];
    gdataxmlelement *ageelement = [agearray objectatindex:0];
    nsstring *age = [ageelement stringvalue];
        //取出sex
    nsarray *sexarray = [item elementsforname:@"sex"];
    gdataxmlelement *sexelement = [sexarray objectatindex:0];
    nsstring *sex = [sexelement stringvalue];
    nslog(@"name=%@---age=%@----sex=%@",name,age,sex);
  }
}

sax解析

  • sax:simple api for xml,基于事件驱动的解析方式,逐行解析数据(采用协议回调机制).
  • nsxmlparser 

1 nsxmlparser是ios自带的xml解析类,采用sax方式解析数据

2 解析过程由nsxmlparserdelegate协议方法回调

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

//遵循协议
@interface rootviewcontroller ()<nsxmlparserdelegate>
//xml解析之sax解析
-(void)xmlsaxmethod{
 //得到需要解析的数据
 nsstring *xmlpath = [[nsbundle mainbundle] pathforresource:@"xmldemo" oftype:@"xml"];
 nsdata *xmldata = [nsdata datawithcontentsoffile:xmlpath];
 //创建sax解析的工具类对象
 nsxmlparser *saxparser = [[nsxmlparser alloc] initwithdata:xmldata];
 //指定代理
 saxparser.delegate = self;
 //开始解析 sax解析是一个同步的过程
 bool isparse = [saxparser parse];
 if (isparse) {

   nslog(@"解析完成");
 }else{
   nslog(@"解析失败");
 }
 nslog(@"我是在解析结束下面");
}

pragma mark - sax解析的代理方法

//开始解析的代理方法
-(void)parserdidstartdocument:(nsxmlparser *)parser {
 nslog(@"开始解析");
 self.saxarray = [nsmutablearray array]; 
}
//开始解析某个节点
//elementname:标签名称
//namespaceuri:命名空间指向的链接
//qname:命名空间的名称
//attributedict:节点的所有属性
-(void)parser:(nsxmlparser )parser didstartelement:(nsstring )elementname namespaceuri:(nsstring )namespaceuri qualifiedname:(nsstring )qname attributes:(nsdictionary<nsstring *,nsstring *> *)attributedict {
 nslog(@"开始解析%@节点",elementname);
 //当开始解析student标签的时候,就应该初始化字典,因为一个字典就对应的是一个学生的信息
 if ([elementname isequaltostring:@"student"]) {
   self.saxdic = [nsmutabledictionary dictionary];
 }
}
//获取节点之间的值
-(void)parser:(nsxmlparser )parser foundcharacters:(nsstring )string {
 nslog(@"取值--------%@",string);
 if (self.valuestring) {//说明有值
   [self.valuestring appendstring:string];
 } else {
   self.valuestring = [nsmutablestring stringwithstring:string];
 }
}
//某个节点结束取值


-(void)parser:(nsxmlparser )parser didendelement:(nsstring )elementname namespaceuri:(nsstring )namespaceuri qualifiedname:(nsstring )qname {
 if ([elementname isequaltostring:@"name"]) {//说明name节点已经取值结束
 [self.saxdic setobject:self.valuestring forkey:elementname];
 }
 if ([elementname isequaltostring:@"age"]) {
 [self.saxdic setobject:self.valuestring forkey:elementname];
 }
 if ([elementname isequaltostring:@"sex"]) {
 [self.saxdic setobject:self.valuestring forkey:elementname];
 }
 if ([elementname isequaltostring:@"student"]) {
 [self.saxarray addobject:self.saxdic];
 }
 self.valuestring = nil;//置空
 nslog(@"结束%@节点的解析",elementname);
}


//结束解析


-(void)parserdidenddocument:(nsxmlparser *)parser {
 //可以使用解析完成的数据
 nslog(@"%@",self.saxarray);
 nslog(@"整个解析结束");
}

//解析出错

-(void)parser:(nsxmlparser )parser parseerroroccurred:(nserror )parseerror {
 nslog(@"解析出现错误-------%@",parseerror.description);
}


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。