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