Can't get xml.etree.ElementTree.iterfind() to work

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?

The docs show that you can use {*} as a namespace (although this information is not highlighted as much as it might be given how common this problem is!). Using tree.iterfind(".//{*}trkpt") seems to work for me.

Thanks! That did the trick.