我正在使用 gpxpy 从 gpx 文件中提取数据。数据示例:
<?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>
代码如下:
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}
现在,我想为其他缺少的 gpx 文件添加
<metadata>..</metadata>
部分。
对我来说,gpxpy 的问题是将“name”和“desc”标签插入 gpxpy 在解析文件时建立的内部数据结构中。 即使查看 gpxpy 源代码我也无法掌握。
我没有 gpxpy,但据我所知,这个模块使用 lxml 来解析 gpx xml。 gpx-文档.
我添加了 3 个函数来操作 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):
""" Replace text and add additional tags 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=False)
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": "No time",
"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")
输出(打印和文件):
<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>No time</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>