How do I select items in an XDocument?

In the XML below, I'm trying to retrieve all the trkpt items so that I can perform a task with the lat / lon attribute values. I thought LINQ to XML would be easiest approach but I can't get any results to be returned in the foreach loop. What am I doing wrong?

This code is in the Main() method of a console app:

var filename = @"C:\temp\sample_output.gpx";

var xDoc = XDocument.Load(filename);

XNamespace xmlns = "http://www.topografix.com/GPX/1/1";
XNamespace gpxtpx = "http://www.garmin.com/xmlschemas/TrackPointExtension/v1";
XNamespace wptx1 = "http://www.garmin.com/xmlschemas/WaypointExtension/v1";
XNamespace gpxx = "http://www.garmin.com/xmlschemas/GpxExtensions/v3";
XNamespace gpxtrkx = "http://www.garmin.com/xmlschemas/TrackStatsExtension/v1";

foreach (var item in xDoc.Descendants(gpxtpx + "trkpt"))
{
    Console.WriteLine(item.Element(gpxtpx + "trkpt").Value);
}

Console.Read();

XML data I'm trying to process with the above code. Lat / Lon values modified.

 <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
    <gpx xmlns="http://www.topografix.com/GPX/1/1"
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
xmlns:gpxtrkx="http://www.garmin.com/xmlschemas/TrackStatsExtension/v1"
xmlns:wptx1="http://www.garmin.com/xmlschemas/WaypointExtension/v1"
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
creator="Oregon 600" version="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
http://www.garmin.com/xmlschemas/GpxExtensions/v3
http://www8.garmin.com/xmlschemas/GpxExtensionsv3.xsd
http://www.garmin.com/xmlschemas/TrackStatsExtension/v1
http://www8.garmin.com/xmlschemas/TrackStatsExtension.xsd
http://www.garmin.com/xmlschemas/WaypointExtension/v1
http://www8.garmin.com/xmlschemas/WaypointExtensionv1.xsd
http://www.garmin.com/xmlschemas/TrackPointExtension/v1
http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd">
        <metadata>
            <link href="http://www.garmin.com">
                <text>Garmin International</text>
            </link>
            <time>2016-04-18T01:19:07Z</time>
        </metadata>
        <trk>
            <name>2016-04-17 20:19:01</name>
            <extensions>
                <gpxx:TrackExtension>
                    <gpxx:DisplayColor>Magenta</gpxx:DisplayColor>
                </gpxx:TrackExtension>
            </extensions>
            <trkseg>
                <trkpt lat="44.123" lon="-89.123">
                    <ele>343.61</ele>
                    <time>2016-04-17T22:53:34Z</time>
                </trkpt>
                <trkpt lat="44.123" lon="-89.123">
                    <ele>343.58</ele>
                    <time>2016-04-17T22:53:35Z</time>
                </trkpt>
                <trkpt lat="44.123" lon="-89.123">
                    <ele>343.56</ele>
                    <time>2016-04-17T22:53:36Z</time>
                </trkpt>
                <trkpt lat="44.123" lon="-89.123">
                    <ele>343.55</ele>
                    <time>2016-04-17T22:53:37Z</time>
                </trkpt>
                <trkpt lat="44.123" lon="-89.123">
                    <ele>343.62</ele>
                    <time>2016-04-17T22:53:38Z</time>
                </trkpt>
            </trkseg>
        </trk>
    </gpx>
Jon Skeet
people
quotationmark

You're using the wrong namespace. The default namespace of the elements (including trkpt) is http://www.topografix.com/GPX/1/1, due to this:

xmlns="http://www.topografix.com/GPX/1/1"

I would strongly recommend that you change your variable name to gpxNs to indicate its value, then use it:

XNamespace gpxNs = "http://www.topografix.com/GPX/1/1";
...
foreach (var item in xDoc.Descendants(gpxNs + "trkpt"))

people

See more on this question at Stackoverflow