如何使用 gpxpy 将元数据添加到 gpx 文件

问题描述 投票:0回答:1

我正在使用 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 源代码我也无法掌握。

python gpx
1个回答
0
投票

我没有 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>
© www.soinside.com 2019 - 2024. All rights reserved.