How to split a gpx ? In each track, segment or trkpt ? (Python)
I had a project in my master’s degree (Sigma) to use python for doing something with a GPX file. There was a project like finding summit or pass, but I choose to edit a GPX to split it into in each of his tracks, segments, or by cutting the file into a specific point.
I choose to use LXML library to parse and edit .gpx, and OS to batch the process with multiple .gpx.
Dealing with the GPX
I don’t post all the code, only the important part, but the project Gpxsplit is available in the Github project page.
When parsing a gpx, you have to define the namespace to edit it with LXML. So my solution was to remove it, and to write a new namespace at the end :
for elem in outRoot.getiterator(): if not hasattr(elem.tag, 'find'): continue # (1) i = elem.tag.find('}') if i >= 0: elem.tag = elem.tag[i+1:] objectify.deannotate(outRoot, cleanup_namespaces=True)With that code (thanks to falsetru), you can open every single file without having his namespace.
Splitting in segment
On the test file, our gpx has two segments. I have define a def segment(): to do the job.
We start by searching the number of segments with nbseg :
# count number of segment nbseg=int(gpx.xpath("count(//trkseg)")) # If more than one segment, splitting file by segment and tell user if nbseg>1: # We do the jobThen, we create every tag (gpx with metadata) :
# add GPX metadata gpx = etree.Element('gpx', xmlns="http://www.topografix.com/GPX/1/1") # add metadata to gpx gpxmetadata = etree.SubElement(gpx, 'metadata') etree.SubElement(gpxmetadata, 'author').text = "GpxSplit" etree.SubElement(gpxmetadata, 'name').text = noext+' split by segment' # add TRK tag (children of GPX) trk = etree.SubElement(gpx, "trk") # add all elements in each segment (trkpt, ele, time...) trk.append(seg)As we are in a loop, we save a file for each loop :
# create a file for each seg # call resultdir() to create result folder if doesn't exist with open(gpxsplit.resultdir()+noext+'_seg'+str(id+1)+'.gpx', mode='wb') as doc: doc.write(etree.tostring(gpx, pretty_print=True))I don’t explain how to do with a track because it’s likely the same to splitting a segment.
Splitting into a specific point
I start by defining a new variable called <em>foundpoint</em>, set to <em>False</em>. By default the script don’t find the point.
# foundpoint=False, means inLon and inLat are currently not found in the GPX file foundpoint=FalseThen I recreate all the hierarchy (metadata, <gpx>, tag…), and here we go, let’s search the point by his lat/lon !
If lat is the same and lon is the name, or if we already found the point, we save all the trkpt in a file called .
Else, we keep searching for this point !if trkpt.attrib['lat']==inLat and trkpt.attrib['lon']==inLon or foundpoint==True: foundpoint=True seg2.append(trkpt) with open(gpxsplit.resultdir()+noext+'_part2'+'.gpx', mode='wb') as doc: doc.write(etree.tostring(gpx2, pretty_print=True)) # Add trkpt to part 1 elif foundpoint==False: seg1.append(trkpt) with open(gpxsplit.resultdir()+noext+'_part1'+'.gpx', mode='wb') as doc: doc.write(etree.tostring(gpx1, pretty_print=True))To finish we tell the user the result of the operation, and if the point was found we indicate the result folder.
if foundpoint==False: print('Point',inLon,'/',inLat,'has not been found') else: print("Done") print("Split file has been stored in \""+gpxsplit.resultdir()+"\" folder")All data are available on the GitHub project page.