I am a C# programmer, so I don't get to take advantage of the cool XML syntax in VB.
Dim itemList1 = From item In rss.<rss>.<channel>.<item> _
Where item.<description>.Value.Contains("LINQ") Or _
item.<title>.Value.Contains("LINQ")
Using C#, I find XPath to be easier to think about, easier to code, easier to understand, than performing a multi-nested select using LINQ to XML. Look at this syntax, it looks like Greek swearing:
var waypoints = from waypoint in gpxDoc.Descendants(gpx + "wpt")
select new
{
Latitude = waypoint.Attribute("lat").Value,
Longitude = waypoint.Attribute("lon").Value,
Elevation = waypoint.Element(gpx + "ele") != null ?
waypoint.Element(gpx + "ele").Value : null,
Name = waypoint.Element(gpx + "name") != null ?
waypoint.Element(gpx + "name").Value : null,
Dt = waypoint.Element(gpx + "cmt") != null ?
waypoint.Element(gpx + "cmt").Value : null
};
All the casting, the heavy syntax, the possibility for NullPointerExceptions. None of this happens with XPath.
I like LINQ in general, and I use it on object collections and databases, but my first go-round with querying XML led me right back to XPath.
Is it just me?
Am I missing something?
EDIT: someone voted to close this as "not a real question". But it is a real question, stated clearly. The question is: Am I misunderstanding
something with LINQ to XML?
Use what you feel the most comfortable with, as long as it gets the job done. I use both methods depending on what I need to do to with XML. It sounds to me like you've got a good handle on what LINQ is good for and what XPath is good for.
Yes, the example you've given is unweildy.
But with LINQ comes the flexibility to refactor away the unweildiness.
Here's an example of how I would improve it. (This is done without any testing at all, and I don't even know the real class names, but it should convey the idea)
static class LinqXmlExtension
{
public static NodeThingy ElementOrNull(this XmlElement ele, string searchString)
{
return (ele.Element(searchString) != null ? ele.Element(searchString).Value : null);
}
}
//
/////////////////////////////////////////////////////////////////
var waypoints = from waypoint in gpxDoc.Descendants(gpx + "wpt")
select new
{
Latitude = waypoint.Attribute("lat").Value,
Longitude = waypoint.Attribute("lon").Value,
Elevation = waypoint.ElementOrNull(gpx + "ele"),
Name = waypoint.ElementOrNull(gpx + "name"),
Dt = waypoint.ElementOrNull(gpx + "cmt")
};
I'm guessing at some of your data types, but you could make your C# LINQ query concise by casting your attribute values:
var waypoints =
from waypoint in gpxDoc.Descendants(gpx + "wpt")
select new
{
Latitude = (decimal)waypoint.Attribute("lat"),
Longitude = (decimal)waypoint.Attribute("lon"),
Elevation = (decimal?)waypoint.Element(gpx + "ele"),
Name = (string)waypoint.Element(gpx + "name"),
Dt = (DateTime?)waypoint.Element(gpx + "cmt")
};
And I'm sure you already know the @ syntax you can use for attributes in VB's XML literals.
I can see your problem but I used LINQ for just reorder a GPX file to get trackpoints in every segment in the correct order and it feels rather straight forward.....
var trksegs = doc.Root.Descendants(ns + "trkseg");
foreach (var trkseg in trksegs)
{
List<XElement> trk = trkseg.Elements(ns + "trkpt")
.OrderBy(x => (string)x.Element(ns + "time")).ToList();
trkseg.RemoveAll();
trkseg.Add(trk);
}
and also fix a bug in a delivered GPX file for time
private static XDocument ConvertTimeElement(XDocument doc)
{
if (doc.Root != null)
{
var times = doc.Root.Descendants(ns + "time").ToList();
foreach (var time in times)
time.SetValue((string)ConvertSpotDateFormat(time));
}
return doc;
}
I think it is rather straight format....
(The problem I fixed http://www.everytrail.com/forum/viewtopic.php?f=4&t=1980&p=6447#p6447)