iOS 解析xml文件之GDataXML重点xPath

本篇文章,主要整合一下网上的GdataXML的使用方法以及介绍下nodesForXPath方法。

之前做一个插件开发的时候用到了这个第三方,当时百度使用方法的时候,发现很多都简单介绍了一些基本方法,对于一个比较复杂的XML的时候,使用nodesForXPath 方法比较便捷,而网上介绍这部分的比较少。
过了一两个月,才开始写这篇文章,很多东西竟然都已经记不清了,😓。当时懒,一直拖,以后还是要及时记录一下,为自己以后翻看,也希望可以帮到别人。

好了,正式开始本篇文章。

GDataXML下载地址:https://github.com/graetzer/GDataXML-HTML

1.导入Pod文件下Classs下的两个文件:

image.png

2.拖个简单的xml文件把,原来当时用的复杂的xml 找不到了。

<track woNo="" jcInstanceId="010000335634_0000034568_CES-SMJC-B787-12-090-00-A_0" sap_id="0000034553" userId="" lastBeginTime="2018-06-27 14:33:16" firstBeginTime="2018-06-27 11:17:09">
    <signoff beginTime="" CK-LEVEL="C" endTime="" uid="" id="signOff_2">
        <handover/>
        <history/>
        <final userType="MECH" file=""/>
        <final userType="INSP" file=""/>
        <final userType="VERF" file=""/>
    </signoff>
    <signoff beginTime="" CK-LEVEL="C" endTime="" uid="" id="signOff_3">
        <handover/>
        <history/>
        <final userType="MECH" file=""/>
        <final userType="INSP" file=""/>
        <final userType="VERF" file=""/>
    </signoff>
    <signoff beginTime="" CK-LEVEL="C" endTime="" uid="" id="signOff_4">
        <handover/>
        <history/>
        <final userType="MECH" file=""/>
        <final userType="INSP" file=""/>
        <final userType="VERF" file=""/>
    </signoff>
    <signoff beginTime="" CK-LEVEL="C" endTime="" uid="" id="signOff_5">
        <handover/>
        <history/>
        <final userType="MECH" file=""/>
        <final userType="INSP" file=""/>
        <final userType="VERF" file=""/>
    </signoff>
    <signoff beginTime="" CK-LEVEL="C" endTime="" uid="" id="signOff_6">
        <handover/>
        <history/>
        <final userType="MECH" file=""/>
        <final userType="INSP" file=""/>
        <final userType="VERF" file=""/>
    </signoff>
</track>

3.修改项目配置

添加libxml2.tbd


image.png

添加Header Search Paths中的选项,增加/usr/include/libxml2


image.png

添加-fno-objc-arc


image.png

OK,至此可以编译运行。

4.方法介绍

在viewcontroller.m中 加个touchesBegan的方法,里面写上测试代码。

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //获取track.xml路径
    NSString *trackPath = [[NSBundle mainBundle] pathForResource:@"track" ofType:@"xml"];
    //通过string创建GDataXMLDocument对象
    NSString *trackStr = [[NSString alloc] initWithContentsOfFile:trackPath encoding:NSUTF8StringEncoding error:nil];
    GDataXMLDocument *trackDoc = [[GDataXMLDocument alloc] initWithXMLString:trackStr encoding:NSUTF8StringEncoding error:nil];
    //1.获取根节点 track
    GDataXMLElement *rootElement = [trackDoc rootElement];
//    NSLog(@"rootElement attributes:%@,children:%@",rootElement.attributes,rootElement.children);
    NSLog(@"rootElemnet first attribute name:%@,stringValue:%@",[rootElement.attributes.firstObject name],[rootElement.attributes.firstObject stringValue]);
}

上面代码的意思可以在xml中表现:


image.png

touchesBegan中添加下面的代码,可以获取到track根节点下面所有的signoff节点

 //4.获取根节点下的signoff节点数组
    NSArray *signOffs = [rootElement elementsForName:@"signoff"];
    //5.打印signoff节点的id
    for (GDataXMLElement *signOff in signOffs) {
        NSLog(@"%@",[signOff.attributes.lastObject stringValue]);
    }

至此,GDataXML的基本方法都在了。总结下来就是:
1.获取父节点:通过GDataXMLDocument的rootElement方法和GDataXMLElement的elementsForName方法
2.获取节点的属性的name和value:通过GDataXMLNode的name和stringValue方法(GDataXMLNode就是节点的attribute的类型)
通过这两个步骤,循环使用就可以获取到xml文件中想要的值。
但是,如果xml中嵌套太多,用以上的方法就比较繁琐,而xPath解决了这个问题

5.xPath直接获取想要的节点

//6. xPath获取所有signoff节点
    NSString *xpath = [NSString stringWithFormat:@"//%@",@"signoff"];
    //track.xml中的signoff节点
    NSError *error;
    NSArray *xArray = [trackDoc nodesForXPath:xpath error:&error];
    if (!error) {
        NSLog(@"signoffs:%@",xArray);
    }else{
        NSLog(@"error:%@",error.localizedDescription);
    }
    
    //7.xPath获取含有某个属性的所有signoff节点,比如含有id字段
    NSString *xpath2 = [NSString stringWithFormat:@"//%@[@%@]",@"signoff",@"id"];
    //track.xml中的signoff节点
    NSError *error2;
    NSArray *xArray2 = [trackDoc nodesForXPath:xpath2 error:&error2];
    if (!error2) {
        NSLog(@"含有id的signoffs:%@",xArray2);
    }else{
        NSLog(@"error:%@",error2.localizedDescription);
    }
    
    //8.xPath获取某个属性为特定值的节点,比如id为signoff_2 的节点
    NSString *xpath3 = [NSString stringWithFormat:@"//%@[@%@='%@']",@"signoff",@"id",@"signOff_2"];
    //track.xml中的signoff节点
    NSError *error3;
    NSArray *xArray3 = [trackDoc nodesForXPath:xpath3 error:&error3];
    if (!error3) {
        NSLog(@"signOff_2节点:%@",xArray3);
    }else{
        NSLog(@"error:%@",error3.localizedDescription);
    }
    
    //9.xPath获取id为signOff_2的节点下的userType为MECH的节点
    NSString *xpath4 = [NSString stringWithFormat:@"//%@[@%@='%@']/%@[@%@='%@']",@"signoff",@"id",@"signOff_2",@"final",@"userType",@"MECH"];
    //track.xml中的signoff节点
    NSError *error4;
    NSArray *xArray4 = [trackDoc nodesForXPath:xpath4 error:&error4];
    if (!error4) {
        NSLog(@"MECH的final节点:%@",xArray4);
    }else{
        NSLog(@"error:%@",error4.localizedDescription);
    }

6.直接获取某个节点

6.1 直接获取所有final节点

 NSString *xpath5 = [NSString stringWithFormat:@"//%@",@"final"];
    NSError *error5;
    NSArray *xArray5 = [trackDoc nodesForXPath:xpath5 error:&error5];
    NSLog(@"%@",xArray5);

6.2 直接获取属性含有userType的节点

    NSString *xpath5 = [NSString stringWithFormat:@"//@%@",@"userType"];
    NSError *error5;
    NSArray *xArray5 = [trackDoc nodesForXPath:xpath5 error:&error5];
    NSLog(@"%@",xArray5);

6.3 获取所有含有字段userType并且值为MECH的final节点

NSString *xpath5 = [NSString stringWithFormat:@"//%@[@%@='%@']",@"final",@"userType",@"MECH"];
    NSError *error5;
    NSArray *xArray5 = [trackDoc nodesForXPath:xpath5 error:&error5];
    NSLog(@"%@",xArray5);

总结xPath

1.//代表遍历所有节点
2.//signoff 代表所有signoff节点
3.//signoff[@id] 代表所有含有id字段的signoff节点 (可以删除track.xml中的一些节点的id看下效果)
4.//signoff[@id='signOff_2'] 代表所有 id 字段为 signOff_2 的signoff节点
5.//signoff[@id='signOff_2']/final[@userType='MECH']代表 id 字段为 signOff_2 的signoff节点 中的userType为MECH的final节点
6.//其他节点,直接可以获取所有的这个‘其他’节点
7.//@属性字段,直接可以获取含有这个‘属性字段’的所有节点
(关于6,7是后来加的,我以前一直以为//代表根节点)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容