本篇文章,主要整合一下網(wǎng)上的GdataXML的使用方法以及介紹下nodesForXPath方法。
之前做一個(gè)插件開發(fā)的時(shí)候用到了這個(gè)第三方,當(dāng)時(shí)百度使用方法的時(shí)候,發(fā)現(xiàn)很多都簡單介紹了一些基本方法,對(duì)于一個(gè)比較復(fù)雜的XML的時(shí)候,使用nodesForXPath 方法比較便捷,而網(wǎng)上介紹這部分的比較少。
過了一兩個(gè)月,才開始寫這篇文章,很多東西竟然都已經(jīng)記不清了,??。當(dāng)時(shí)懶,一直拖,以后還是要及時(shí)記錄一下,為自己以后翻看,也希望可以幫到別人。
好了,正式開始本篇文章。
GDataXML下載地址:https://github.com/graetzer/GDataXML-HTML
1.導(dǎo)入Pod文件下Classs下的兩個(gè)文件:

2.拖個(gè)簡單的xml文件把,原來當(dāng)時(shí)用的復(fù)雜的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.修改項(xiàng)目配置
添加libxml2.tbd

添加Header Search Paths中的選項(xiàng),增加/usr/include/libxml2

添加-fno-objc-arc

OK,至此可以編譯運(yùn)行。
4.方法介紹
在viewcontroller.m中 加個(gè)touchesBegan的方法,里面寫上測(cè)試代碼。
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//獲取track.xml路徑
NSString *trackPath = [[NSBundle mainBundle] pathForResource:@"track" ofType:@"xml"];
//通過string創(chuàng)建GDataXMLDocument對(duì)象
NSString *trackStr = [[NSString alloc] initWithContentsOfFile:trackPath encoding:NSUTF8StringEncoding error:nil];
GDataXMLDocument *trackDoc = [[GDataXMLDocument alloc] initWithXMLString:trackStr encoding:NSUTF8StringEncoding error:nil];
//1.獲取根節(jié)點(diǎn) 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中表現(xiàn):

touchesBegan中添加下面的代碼,可以獲取到track根節(jié)點(diǎn)下面所有的signoff節(jié)點(diǎn)
//4.獲取根節(jié)點(diǎn)下的signoff節(jié)點(diǎn)數(shù)組
NSArray *signOffs = [rootElement elementsForName:@"signoff"];
//5.打印signoff節(jié)點(diǎn)的id
for (GDataXMLElement *signOff in signOffs) {
NSLog(@"%@",[signOff.attributes.lastObject stringValue]);
}
至此,GDataXML的基本方法都在了??偨Y(jié)下來就是:
1.獲取父節(jié)點(diǎn):通過GDataXMLDocument的rootElement方法和GDataXMLElement的elementsForName方法
2.獲取節(jié)點(diǎn)的屬性的name和value:通過GDataXMLNode的name和stringValue方法(GDataXMLNode就是節(jié)點(diǎn)的attribute的類型)
通過這兩個(gè)步驟,循環(huán)使用就可以獲取到xml文件中想要的值。
但是,如果xml中嵌套太多,用以上的方法就比較繁瑣,而xPath解決了這個(gè)問題
5.xPath直接獲取想要的節(jié)點(diǎn)
//6. xPath獲取所有signoff節(jié)點(diǎn)
NSString *xpath = [NSString stringWithFormat:@"http://%@",@"signoff"];
//track.xml中的signoff節(jié)點(diǎn)
NSError *error;
NSArray *xArray = [trackDoc nodesForXPath:xpath error:&error];
if (!error) {
NSLog(@"signoffs:%@",xArray);
}else{
NSLog(@"error:%@",error.localizedDescription);
}
//7.xPath獲取含有某個(gè)屬性的所有signoff節(jié)點(diǎn),比如含有id字段
NSString *xpath2 = [NSString stringWithFormat:@"http://%@[@%@]",@"signoff",@"id"];
//track.xml中的signoff節(jié)點(diǎn)
NSError *error2;
NSArray *xArray2 = [trackDoc nodesForXPath:xpath2 error:&error2];
if (!error2) {
NSLog(@"含有id的signoffs:%@",xArray2);
}else{
NSLog(@"error:%@",error2.localizedDescription);
}
//8.xPath獲取某個(gè)屬性為特定值的節(jié)點(diǎn),比如id為signoff_2 的節(jié)點(diǎn)
NSString *xpath3 = [NSString stringWithFormat:@"http://%@[@%@='%@']",@"signoff",@"id",@"signOff_2"];
//track.xml中的signoff節(jié)點(diǎn)
NSError *error3;
NSArray *xArray3 = [trackDoc nodesForXPath:xpath3 error:&error3];
if (!error3) {
NSLog(@"signOff_2節(jié)點(diǎn):%@",xArray3);
}else{
NSLog(@"error:%@",error3.localizedDescription);
}
//9.xPath獲取id為signOff_2的節(jié)點(diǎn)下的userType為MECH的節(jié)點(diǎn)
NSString *xpath4 = [NSString stringWithFormat:@"http://%@[@%@='%@']/%@[@%@='%@']",@"signoff",@"id",@"signOff_2",@"final",@"userType",@"MECH"];
//track.xml中的signoff節(jié)點(diǎn)
NSError *error4;
NSArray *xArray4 = [trackDoc nodesForXPath:xpath4 error:&error4];
if (!error4) {
NSLog(@"MECH的final節(jié)點(diǎn):%@",xArray4);
}else{
NSLog(@"error:%@",error4.localizedDescription);
}
6.直接獲取某個(gè)節(jié)點(diǎn)
6.1 直接獲取所有final節(jié)點(diǎn)
NSString *xpath5 = [NSString stringWithFormat:@"http://%@",@"final"];
NSError *error5;
NSArray *xArray5 = [trackDoc nodesForXPath:xpath5 error:&error5];
NSLog(@"%@",xArray5);
6.2 直接獲取屬性含有userType的節(jié)點(diǎn)
NSString *xpath5 = [NSString stringWithFormat:@"http://@%@",@"userType"];
NSError *error5;
NSArray *xArray5 = [trackDoc nodesForXPath:xpath5 error:&error5];
NSLog(@"%@",xArray5);
6.3 獲取所有含有字段userType并且值為MECH的final節(jié)點(diǎn)
NSString *xpath5 = [NSString stringWithFormat:@"http://%@[@%@='%@']",@"final",@"userType",@"MECH"];
NSError *error5;
NSArray *xArray5 = [trackDoc nodesForXPath:xpath5 error:&error5];
NSLog(@"%@",xArray5);
總結(jié)xPath
1.//代表遍歷所有節(jié)點(diǎn)
2.//signoff 代表所有signoff節(jié)點(diǎn)
3.//signoff[@id] 代表所有含有id字段的signoff節(jié)點(diǎn) (可以刪除track.xml中的一些節(jié)點(diǎn)的id看下效果)
4.//signoff[@id='signOff_2'] 代表所有 id 字段為 signOff_2 的signoff節(jié)點(diǎn)
5.//signoff[@id='signOff_2']/final[@userType='MECH']代表 id 字段為 signOff_2 的signoff節(jié)點(diǎn) 中的userType為MECH的final節(jié)點(diǎn)
6.//其他節(jié)點(diǎn),直接可以獲取所有的這個(gè)‘其他’節(jié)點(diǎn)
7.//@屬性字段,直接可以獲取含有這個(gè)‘屬性字段’的所有節(jié)點(diǎn)
(關(guān)于6,7是后來加的,我以前一直以為//代表根節(jié)點(diǎn))