iOS之GPX文件讀寫KissXML

GPX(GPS eXchange Format咕幻,GPS交換格式)是一個XML格式,為應(yīng)用軟件設(shè)計的通用GPS數(shù)據(jù)格式翰绊,專門用來存儲地理信息箭养。

一個GPX文件當(dāng)中可能包含一些路點(waypoint)及一些軌跡點(trackpoint)。 以全球定位系統(tǒng)(GPS設(shè)備)所產(chǎn)生的GPX檔為例偶宫, 路點可能是各自獨立互不相干的重要標(biāo)記點非迹, 例如照相的地點或用戶手動標(biāo)記的休息站或路口等等;至于GPS設(shè)備自動定時記錄的則是軌跡點纯趋。 有順序的一串軌跡點構(gòu)成一個軌跡(track)或者路程(route)憎兽。軌跡是一個人曾經(jīng)走過的記錄,可能包含走錯的路等等吵冒;路程則經(jīng)常是建議未來用路人可以走的路徑纯命。所以,一般來講痹栖,軌跡里的點扎附,包含時間信息,路程里的點结耀,則沒有時間信息留夜。點擊查看GPX文件內(nèi)容示例

1、在iOS開發(fā)當(dāng)中图甜,可以通過Xcode創(chuàng)建一個GPX文件碍粥,如圖:

從上圖中,可以很明確的看出GPX文件就是XML文件黑毅。

2嚼摩、可以從其他地方下載GPX文件放進項目工程使用。
這種方法可以用來給模擬器虛擬定位測試使用矿瘦。Xcode模擬器可以指定當(dāng)前Location來機進行地理位置測試枕面。

如上圖中,紅色箭頭的Test就是我們剛剛創(chuàng)建的gpx文件缚去。下面紅色箭頭可以添加GPX文件到項目里面潮秘。
然后就可以在模擬器選項里面選擇所需要的GPX文件信息。
這里有一篇釘釘模擬器模擬打卡定位的文章

3易结、下面來說說代碼創(chuàng)建GPX文件的做法枕荞。
既然GPX就是一個XML的話,那創(chuàng)建GPX就是創(chuàng)建XML搞动,說道代碼創(chuàng)建XML文件的話躏精,iOS上可以搜出幾個常用的庫,具體就不詳細說了鹦肿,這里只結(jié)合項目需求來說說自己功能需求對應(yīng)的GPX文件生成與讀取矗烛。

iOS SDK 提供了兩個xml框架。
NSXMLParser:它是基于objective-c語言的sax解析框架箩溃,是iOS SDK默認(rèn)的xml解析框架瞭吃,不支持dom模式碌识。
libxml2: 它是基于c語言的xml解析器,被蘋果整合在iOS SDK中虱而,支持sax和dom模式筏餐。

第三方xml解析框架
tbxml:它是輕量級的dom模式解析庫,不支持xml文檔驗證和xpath,只能讀取xml文檔牡拇,不能寫xml文檔魁瞪。
touchxml:它是基于dom模式的解析庫,與 tbxml類似惠呼,只能讀取xml文檔导俘,不能寫xml文檔。
KissXML:它是基于dom模式的解析庫剔蹋,基于touchxml,主要的不同是可以寫入xml文檔旅薄。
Gdataxml:它是基于dom模式的解析庫,由google開發(fā)泣崩,可以讀寫xml文檔少梁,支持xpath查詢。

項目里面我使用的是KissXML來進行數(shù)據(jù)的生成與解析矫付。
項目需求是記錄一段運動軌跡凯沪,記錄下每個定位點的數(shù)據(jù)信息,包括“經(jīng)緯度”买优、“海拔”妨马、“距離”、“速度”杀赢、“時間”等相關(guān)軌跡信息烘跺,用來在地圖控件上繪制一條運動軌跡線條。所以在獲取定位點信息之后脂崔,必須把數(shù)據(jù)寫入GPX文件滤淳,上傳到服務(wù)器保存起來⊥迅荩看下最終生成的GPX定位信息文件:


這個XML根節(jié)點為gpx娇钱,wpt為gpx的子節(jié)點,在wpt子節(jié)點的下面就是包含location的定位信息伤柄,n個wpt子節(jié)點定位信息組成了一個完整的GPX文件绊困。(gpx、wpt等是自己的命名)
所以采用KissXML來生成的話适刀,就如下面代碼示例:

- (NSString *)writeXmlDocumentCallbackPath:(YTTrackRoute *)trackRoute
{
    //gpx(root根)
    DDXMLElement *gpxElement = [[DDXMLElement alloc]initWithName:@"gpx"];
    DDXMLNode *gpxUserID = [DDXMLNode attributeWithName:@"userid" stringValue:[[DataManagerObject shareDataManagerObject] getWildtoID]];
    [gpxElement addAttribute:gpxUserID];
    DDXMLNode *gpxUserName = [DDXMLNode attributeWithName:@"nickname" stringValue:[[DataManagerObject shareDataManagerObject] getUserNickName]];
    [gpxElement addAttribute:gpxUserName];
    DDXMLNode *gpxDevice = [DDXMLNode attributeWithName:@"device" stringValue:[UIDevice machineModelName]];
    [gpxElement addAttribute:gpxDevice];
    DDXMLNode *gpxVersion = [DDXMLNode attributeWithName:@"appversion" stringValue:YTAPPVersion];
    [gpxElement addAttribute:gpxVersion];
    DDXMLNode *gpxChannel = [DDXMLNode attributeWithName:@"channel" stringValue:@"wildto"];
    [gpxElement addAttribute:gpxChannel];
    DDXMLNode *gpxClient = [DDXMLNode attributeWithName:@"client" stringValue:YT_IOS_DEVICE];
    [gpxElement addAttribute:gpxClient];
    
    NSArray *points = trackRoute.route_points;
    for (NSInteger i = 0; i < points.count; i ++) {
        @autoreleasepool {
            YTRoutePoint *point = points[i];
            
            //wpt元素(包含經(jīng)緯度兩個屬性)
            DDXMLElement *wptElement = [[DDXMLElement alloc]initWithName:@"wpt"];
            DDXMLNode *wptLonAtt = [DDXMLNode attributeWithName:@"lon" stringValue:[NSString stringWithFormat:@"%f",point.lon]];
            [wptElement addAttribute:wptLonAtt];
            DDXMLNode *wptLatAtt = [DDXMLNode attributeWithName:@"lat" stringValue:[NSString stringWithFormat:@"%f",point.lat]];
            [wptElement addAttribute:wptLatAtt];
            
            //速度
            DDXMLElement *speedElement = [[DDXMLElement alloc]initWithName:@"speed" stringValue:[NSString stringWithFormat:@"%f",point.speed]];
            [wptElement addChild:speedElement];
            
            //海拔
            DDXMLElement *altudeElement = [[DDXMLElement alloc]initWithName:@"level" stringValue:[NSString stringWithFormat:@"%f",point.altude]];
            [wptElement addChild:altudeElement];
            
            //時間點(時間戳)
            DDXMLElement *creatTimeElement = [[DDXMLElement alloc]initWithName:@"time" stringValue:[NSString stringWithFormat:@"%ld",(long)point.create_time]];
            [wptElement addChild:creatTimeElement];
            
            //坡度
            DDXMLElement *slopeElement = [[DDXMLElement alloc]initWithName:@"slope" stringValue:[NSString stringWithFormat:@"%f",point.slope]];
            [wptElement addChild:slopeElement];
            
            //當(dāng)前點經(jīng)過的總距離
            DDXMLElement *distacneElement = [[DDXMLElement alloc]initWithName:@"distacne" stringValue:[NSString stringWithFormat:@"%.1f",point.distance]];
            [wptElement addChild:distacneElement];
            
            [gpxElement addChild:wptElement];
        }
    }
    
    NSString *xmlString = [@"<?xml version=\"1.0\"?>" stringByAppendingString:[gpxElement XMLString]];
//    DLog(@"xmlString  %@",xmlString);
    
    DDXMLDocument *xmlDocument = [[DDXMLDocument alloc]initWithXMLString:xmlString options:0 error:nil];
    NSString *path = [NSString stringWithFormat:@"%@/%@.gpx",[self userFolderPath],trackRoute.route_app_id];
    DLog(@"路勁 == %@",path);
    
    NSString *result = [NSString stringWithFormat:@"%@",xmlDocument];
    BOOL writed = [result writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
    if (writed) {
        return path;
    }
    return nil;
}

有生成就有讀取秤朗,下面是讀取的代碼示例:

- (NSArray *)readGPXFileToPoints:(NSString *)filePath route_app_id:(NSString *)route_app_id
{
    //轉(zhuǎn)成XML字符串
    NSString *xmlString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    
    DDXMLDocument *xmlDoc = [[DDXMLDocument alloc]initWithXMLString:xmlString options:0 error:nil];
    
    //開始解析
    NSArray *children = [xmlDoc nodesForXPath:@"gpx/wpt" error:nil];
    
    NSMutableArray *points = [NSMutableArray arrayWithCapacity:children.count];
    
    //遍歷每個元素
    YTRoutePoint *prevPoint = nil;
    for (DDXMLElement *child in children) {
        @autoreleasepool {
            NSString *lat =[[child attributeForName:@"lat"] stringValue];
            NSString *lon =[[child attributeForName:@"lon"] stringValue];
            
            DDXMLElement *speedEle = [child elementForName:@"speed"];
            DDXMLElement *timeEle = [child elementForName:@"time"];
            DDXMLElement *distacneEle = [child elementForName:@"distacne"];
            DDXMLElement *levelEle = [child elementForName:@"level"];
            DDXMLElement *slopeEle = [child elementForName:@"slope"];
            
            YTRoutePoint *point = [[YTRoutePoint alloc]init];
            point.route_app_id = route_app_id;
            point.lon = [lon doubleValue];
            point.lat = [lat doubleValue];
            point.speed = [[speedEle stringValue] doubleValue];
            point.altude = [[levelEle stringValue] doubleValue];
            point.distance = [[distacneEle stringValue] doubleValue];
            point.slope = [[slopeEle stringValue] doubleValue];
            point.create_time = [[timeEle stringValue] integerValue];
            
            //去重
            if(!prevPoint) {
                [points addObject:point];
                prevPoint = point;
            }
            else {
                if(prevPoint.lat == point.lat && prevPoint.lon == point.lon) {
                    continue;
                }
                [points addObject:point];
                prevPoint = point;
            }
            
        }
    }
    
    return [NSArray arrayWithArray:points];
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市笔喉,隨后出現(xiàn)的幾起案子取视,更是在濱河造成了極大的恐慌硝皂,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件作谭,死亡現(xiàn)場離奇詭異稽物,居然都是意外死亡,警方通過查閱死者的電腦和手機折欠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門贝或,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人锐秦,你說我怎么就攤上這事咪奖。” “怎么了酱床?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵羊赵,是天一觀的道長。 經(jīng)常有香客問我扇谣,道長昧捷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任罐寨,我火速辦了婚禮料身,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘衩茸。我一直安慰自己芹血,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布楞慈。 她就那樣靜靜地躺著幔烛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪囊蓝。 梳的紋絲不亂的頭發(fā)上饿悬,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機與錄音聚霜,去河邊找鬼狡恬。 笑死,一個胖子當(dāng)著我的面吹牛蝎宇,可吹牛的內(nèi)容都是我干的弟劲。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼姥芥,長吁一口氣:“原來是場噩夢啊……” “哼兔乞!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤庸追,失蹤者是張志新(化名)和其女友劉穎霍骄,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體淡溯,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡读整,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了咱娶。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绘沉。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖豺总,靈堂內(nèi)的尸體忽然破棺而出车伞,到底是詐尸還是另有隱情,我是刑警寧澤喻喳,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布另玖,位于F島的核電站,受9級特大地震影響表伦,放射性物質(zhì)發(fā)生泄漏谦去。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一蹦哼、第九天 我趴在偏房一處隱蔽的房頂上張望鳄哭。 院中可真熱鬧,春花似錦纲熏、人聲如沸妆丘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勺拣。三九已至,卻和暖如春鱼填,著一層夾襖步出監(jiān)牢的瞬間药有,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工苹丸, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留愤惰,地道東北人。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓赘理,卻偏偏與公主長得像宦言,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子感憾,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,691評論 2 361