只有我吗?与XPath相比,我发现LINQ to XML有点麻烦

时间:2009-09-18 04:23:12

标签: .net linq xpath linq-to-xml

我是一名C#程序员,所以我无法利用VB中的酷XML语法。

Dim itemList1 = From item In rss.<rss>.<channel>.<item> _
                Where item.<description>.Value.Contains("LINQ") Or _
                      item.<title>.Value.Contains("LINQ")

使用C#,我发现XPath比使用LINQ to XML执行多嵌套选择更容易思考,更容易编码,更容易理解。看看这个语法,看起来像希腊语咒骂:

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 
          }; 

所有强制转换,重语法,NullPointerExceptions的可能性。 XPath不会发生这种情况。

我一般都喜欢LINQ,而且我在对象集合和数据库上使用它,但是我第一次查询XML时又回到了XPath。

只是我吗?

我错过了什么吗?


编辑:有人投票决定将其视为“不是真正的问题”。但它一个真实的问题,清楚地说明了。问题是:我误解了 使用LINQ to XML的东西?

4 个答案:

答案 0 :(得分:5)

是的,你给出的例子是unweildy。

但是使用LINQ可以灵活地重构不合情理。

这是我如何改进它的一个例子。 (这完全没有任何测试,我甚至不知道真正的类名,但它应该传达这个想法)

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")           
                 };

答案 1 :(得分:4)

使用您感觉最舒服的东西,只要完成工作即可。我根据XML需要做什么来使用这两种方法。听起来对你来说,你已经很好地理解了LINQ的优点以及XPath的优点。

答案 2 :(得分:1)

我猜测你的某些数据类型,但你可以通过强制转换你的属性值来简化你的C#LINQ查询:

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")
    };

我相信你已经知道可以用于VB的XML文字中的属性的@语法。

答案 3 :(得分:1)

我可以看到你的问题,但我使用LINQ只是重新排序一个GPX文件,以正确的顺序在每个段中获取跟踪点,感觉相当直接......

       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);
        }

并修复已交付的GPX文件中的错误

  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;
    }

我认为这是相当直接的格式......

(我修复的问题http://www.everytrail.com/forum/viewtopic.php?f=4&t=1980&p=6447#p6447