Consider this small GPX file adapted from one of my rides on Strava:
<?xml version="1.0" encoding="UTF-8"?>
<gpx 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 http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd" creator="StravaGPX" version="1.1" xmlns="http://www.topografix.com/GPX/1/1" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3">
<metadata>
<time>2025-12-24T16:46:26Z</time>
</metadata>
<trk>
<name>Winnetka</name>
<type>cycling</type>
<trkseg>
<trkpt lat="42.0" lon="-87.5">
<ele>183.1</ele>
<time>2025-12-24T16:46:26Z</time>
<extensions>
<gpxtpx:TrackPointExtension>
<gpxtpx:atemp>25</gpxtpx:atemp>
</gpxtpx:TrackPointExtension>
</extensions>
</trkpt>
<trkpt lat="42.0" lon="-87.5">
<ele>183.1</ele>
<time>2025-12-24T16:46:27Z</time>
<extensions>
<gpxtpx:TrackPointExtension>
<gpxtpx:atemp>25</gpxtpx:atemp>
</gpxtpx:TrackPointExtension>
</extensions>
</trkpt>
<trkpt lat="42.0" lon="-87.5">
<ele>183.1</ele>
<time>2025-12-24T16:46:28Z</time>
<extensions>
<gpxtpx:TrackPointExtension>
<gpxtpx:atemp>25</gpxtpx:atemp>
</gpxtpx:TrackPointExtension>
</extensions>
</trkpt>
</trkseg>
</trk>
</gpx>
I can used tree.iter() to walk the object tree:
>>> tree = ET.parse('/Users/skip/tmp/short.gpx')
>>> for child in tree.iter():
... print(child.tag, child.attrib)
...
{http://www.topografix.com/GPX/1/1}gpx {'creator': 'StravaGPX', 'version': '1.1', '{http://www.w3.org/2001/XMLSchema-instance}schemaLocation': 'http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd'}
{http://www.topografix.com/GPX/1/1}metadata {}
{http://www.topografix.com/GPX/1/1}time {}
{http://www.topografix.com/GPX/1/1}trk {}
{http://www.topografix.com/GPX/1/1}name {}
{http://www.topografix.com/GPX/1/1}type {}
{http://www.topografix.com/GPX/1/1}trkseg {}
{http://www.topografix.com/GPX/1/1}trkpt {'lat': '42.0', 'lon': '-87.5'}
...
I would like to enumerate just the trkpt tags, so I tried using the iterfind() method, but can’t seem to make it work. It always comes up empty unless I embed the namespace in the argument to iterfind(). Here’s my latest failed attempt:
>>> for elt in tree.iterfind(".//trkpt"):
... txt = elt.text
... dots = "..." if len(txt) > 100 else ""
... print(f"{elt.tag} {elt.text[0:100]}{dots}")
...
>>>
This whole XPath thing is a mystery to me. The documentation about it doesn’t help a novice like me either. How do I specify the trkpt tags which exist in the {http://www.topografix.com/GPX/1/1} namespace without specifying the precise namespace? I see this:
For XML with namespaces, use the usual qualified {namespace}tag notation:
Copy
# All dublin-core "title" tags in the document
root.findall(".//{http://purl.org/dc/elements/1.1/}title")```
Is there no way to wildcard the namespace? Maybe I need to pluck the namespace from the gpx tag’s attributes, but I can’t find an xmlns attribute there (despite it obviously being visible as an attribute in the above print):
>>> pprint.pprint(root.attrib)
{'creator': 'StravaGPX',
'version': '1.1',
'{http://www.w3.org/2001/XMLSchema-instance}schemaLocation': 'http://www.topografix.com/GPX/1/1 '
'http://www.topografix.com/GPX/1/1/gpx.xsd '
'http://www.garmin.com/xmlschemas/GpxExtensions/v3 '
'http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd '
'http://www.garmin.com/xmlschemas/TrackPointExtension/v1 '
'http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd'}
>>>
What if I get a GPX file from some other source (say, RideWithGPS) which contains <trkpt> tags but uses different namespace names? (To say that I hate XML at this point would be a big understatement.)
What do I need to do to (flexibly) pluck all trkpt tags from a GPX file of possibly unknown origin?