Reputation: 1
I am extracting data from gpx files using gpxpy. Data example:
<?xml version="1.0" encoding="UTF-8"?>
<gpx
xmlns="http://www.topografix.com/GPX/1/1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
version="1.1"
creator="xyz3">
<metadata>
<name>Cubieres-St.Paul</name>
<desc>Export from GpsPrune</desc>
</metadata>
<trk>
...
</trk>
</gpx>
The code goes like this:
def gpxinfo(gpx): # gpx =: class gpxpy.gpx.GPX
"extract from GPX-file"
gpxname = "No gpxname"
description = "No description"
if gpx.name:
gpxname = gpx.name
if gpx.description:
description = gpx.description
return {'gpxname': gpxname,
'description': description}
Now, I want to add the <metadata>..</metadata>
section for other gpx files where it is missing.
The problem in gpxpy for me is to insert the 'name' and 'desc' tags into the internal data structure that gpxpy builds up when parsing the file. I don't come to grips even by looking into the gpxpy source code.
Upvotes: 0
Views: 136
Reputation: 3417
I don’t have gpxpy, but what I read, this Modul use lxml for parsing the gpx. gpx-Documentation.
I added 3 functions to manipulate the gpx:
from lxml import etree as et
from io import BytesIO
gpx_ = b"""\
<?xml version="1.0" encoding="UTF-8"?>
<gpx xmlns="http://www.topografix.com/GPX/1/1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
version="1.1"
creator="xyz3">
<wpt> wptType </wpt>
<rte> rteType </rte>
<trk> trkType </trk>
<extensions> extensionsType </extensions>
</gpx>
"""
def change_meta(root, namespaces, my_meta_data):
""" Replace text for existing tags """
for k,v in my_meta_data.items():
try:
t = root.find(f"./metadata/{k}", ns)
t.text = v
except:
print(f"Tag {k} not found in gpx file")
return root
def extend_meta(root, namespaces, my_meta_data):
""" Replace text and add additional tags in metadata """
ns = namespaces
meta = root.find(".//metadata", ns)
d = []
# Change existing nodes
for elem in meta.iter():
for k,v in my_meta_data.items():
if k in elem.tag:
elem.text = v
d.append(elem.tag.split('}')[1])
# add missing nodes
for k,v in my_meta_data.items():
if k not in d:
t = et.Element(f"{{http://www.topografix.com/GPX/1/1}}{k}")
t.text = v
meta.append(t)
return root
def create_meta(root, namespaces, my_meta_data):
""" Add missing metadata tag and text in metadata """
ns = namespaces
meta = et.Element('metadata')
root.insert(0, meta)
for k,v in my_meta_data.items():
t = et.Element(f"{{http://www.topografix.com/GPX/1/1}}{k}")
t.text = v
meta.append(t)
return root
def write_gpx(root, filename):
et.indent(root, space=' ')
et.dump(root)
tree = et.ElementTree(root)
tree.write(filename, xml_declaration=True, encoding='UTF-8')
if __name__ == "__main__":
file = BytesIO(gpx_)
root = et.parse(file).getroot()
#root = et.parse("landscape.gpx")
ns = root.nsmap
#print(root)
#print(ns)
# My new data tag-name : text
meta_data = {
"name" :"No gpxname",
"desc": "No description",
"author": "No author",
"copyright": "No copyright",
"link": "No link",
"time": "1970-01-31T23:59:59Z",
"keywords": "No keywords",
"bounds": "No bounds",
"extensions": "No extensions"}
# Change metadata
#new_gpx = change_meta(root, ns, meta_data)
#et.dump(new_gpx)
# Change and extend metadata
#new1_gpx = extend_meta(root, ns, meta_data)
# add metadata if missing
meta_gpx = create_meta(root, ns, meta_data)
# print and write the changed gpx
write_gpx(meta_gpx, "newGpx.gpx")
Output (print and file):
<gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" version="1.1" creator="xyz3">
<metadata>
<name>No gpxname</name>
<desc>No description</desc>
<author>No author</author>
<copyright>No copyright</copyright>
<link>No link</link>
<time> 1970-01-31T23:59:59Z</time>
<keywords>No keywords</keywords>
<bounds>No bounds</bounds>
<extensions>No extensions</extensions>
</metadata>
<wpt> wptType </wpt>
<rte> rteType </rte>
<trk> trkType </trk>
<extensions> extensionsType </extensions>
</gpx>
Upvotes: 0