Add a conveter for OSMand favorites
This commit is contained in:
parent
5b328e4d63
commit
674f406fba
1 changed files with 106 additions and 0 deletions
106
gpx_to_osmand_favorites.py
Executable file
106
gpx_to_osmand_favorites.py
Executable file
|
|
@ -0,0 +1,106 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
|
GPX_NS = "http://www.topografix.com/GPX/1/1"
|
||||||
|
OSMAND_NS = "https://osmand.net"
|
||||||
|
|
||||||
|
ET.register_namespace("", GPX_NS)
|
||||||
|
ET.register_namespace("osmand", OSMAND_NS)
|
||||||
|
|
||||||
|
def iso_now_z():
|
||||||
|
return datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
|
||||||
|
|
||||||
|
def localname(tag):
|
||||||
|
return tag.split("}", 1)[-1] if "}" in tag else tag
|
||||||
|
|
||||||
|
def find_child_by_localname(parent, wanted):
|
||||||
|
for ch in list(parent):
|
||||||
|
if localname(ch.tag) == wanted:
|
||||||
|
return ch
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_metadata_name_anyns(root):
|
||||||
|
md = find_child_by_localname(root, "metadata")
|
||||||
|
if md is None:
|
||||||
|
return None
|
||||||
|
nm = find_child_by_localname(md, "name")
|
||||||
|
if nm is None:
|
||||||
|
return None
|
||||||
|
txt = (nm.text or "").strip()
|
||||||
|
return txt or None
|
||||||
|
|
||||||
|
def guess_group(in_path, root, prefix):
|
||||||
|
base = get_metadata_name_anyns(root)
|
||||||
|
if not base:
|
||||||
|
base = os.path.splitext(os.path.basename(in_path))[0]
|
||||||
|
if prefix:
|
||||||
|
return f"{prefix.rstrip('/')}/{base}"
|
||||||
|
return base
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) not in (3, 4):
|
||||||
|
print(
|
||||||
|
"Usage: gpx_to_osmand_favorites_autogroup_fixed.py input.gpx output.gpx [prefix]\n"
|
||||||
|
"Example: gpx_to_osmand_favorites_autogroup_fixed.py 4x4.gpx 4x4_osmand.gpx Norwegen",
|
||||||
|
file=sys.stderr
|
||||||
|
)
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
in_path = sys.argv[1]
|
||||||
|
out_path = sys.argv[2]
|
||||||
|
prefix = sys.argv[3] if len(sys.argv) == 4 else ""
|
||||||
|
|
||||||
|
tree = ET.parse(in_path)
|
||||||
|
root = tree.getroot()
|
||||||
|
|
||||||
|
group = guess_group(in_path, root, prefix)
|
||||||
|
|
||||||
|
in_wpts = [el for el in root.iter() if localname(el.tag) == "wpt"]
|
||||||
|
if not in_wpts:
|
||||||
|
raise SystemExit(f"No <wpt> elements found in {in_path}")
|
||||||
|
|
||||||
|
out_root = ET.Element(f"{{{GPX_NS}}}gpx", {
|
||||||
|
"version": "1.1",
|
||||||
|
"creator": "gpx_to_osmand_favorites_autogroup_fixed.py",
|
||||||
|
})
|
||||||
|
|
||||||
|
md = ET.SubElement(out_root, f"{{{GPX_NS}}}metadata")
|
||||||
|
ET.SubElement(md, f"{{{GPX_NS}}}name").text = f"OsmAnd favorites: {group}"
|
||||||
|
ET.SubElement(md, f"{{{GPX_NS}}}time").text = iso_now_z()
|
||||||
|
|
||||||
|
written = 0
|
||||||
|
for w in in_wpts:
|
||||||
|
lat = w.attrib.get("lat")
|
||||||
|
lon = w.attrib.get("lon")
|
||||||
|
if lat is None or lon is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
out_wpt = ET.SubElement(out_root, f"{{{GPX_NS}}}wpt", {"lat": str(lat), "lon": str(lon)})
|
||||||
|
|
||||||
|
# Copy common fields if present
|
||||||
|
for ch in list(w):
|
||||||
|
ln = localname(ch.tag)
|
||||||
|
if ln in ("name", "cmt", "desc", "ele", "time") and ch.text not in (None, ""):
|
||||||
|
ET.SubElement(out_wpt, f"{{{GPX_NS}}}{ln}").text = ch.text
|
||||||
|
|
||||||
|
# Ensure we have a name
|
||||||
|
if find_child_by_localname(out_wpt, "name") is None:
|
||||||
|
ET.SubElement(out_wpt, f"{{{GPX_NS}}}name").text = f"Favorite {written+1}"
|
||||||
|
|
||||||
|
# OsmAnd favorites group (key field)
|
||||||
|
ET.SubElement(out_wpt, f"{{{GPX_NS}}}type").text = group
|
||||||
|
|
||||||
|
# Optional OsmAnd hint (safe if ignored)
|
||||||
|
ext = ET.SubElement(out_wpt, f"{{{GPX_NS}}}extensions")
|
||||||
|
ET.SubElement(ext, f"{{{OSMAND_NS}}}category").text = group
|
||||||
|
|
||||||
|
written += 1
|
||||||
|
|
||||||
|
ET.ElementTree(out_root).write(out_path, encoding="UTF-8", xml_declaration=True)
|
||||||
|
print(f"Wrote {written} waypoint(s) to {out_path} with OsmAnd favorites group '{group}'")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue