2008-11-10 99 views
14

我与具有结构(部分)现有的XML文档的工作,像这样:的LINQ to XML可选元素查询

<Group> 
    <Entry> 
     <Name> Bob </Name> 
     <ID> 1 </ID> 
    </Entry> 
    <Entry> 
     <Name> Larry </Name> 
    </Entry> 
</Group> 

我使用LINQ to XML查询的XDocument检索所有这些条目如下:

var items = from g in xDocument.Root.Descendants("Group").Elements("Entry") 
    select new 
    { 
     name = (string)g.element("Name").Value, 
     id = g.Elements("ID").Count() > 0 ? (string)g.Element("ID").Value : "none" 
    }; 

“ID”元素并不总是存在,所以我的解决方案是上面的Count()爵士乐。但我想知道是否有人有更好的方法来做到这一点。我仍然对这个新东西感到满意,我怀疑可能有更好的方法来做到这一点,而不是我目前正在做的事情。

有没有更好的/更喜欢的方式来做我想要的?

回答

23

​​实际上有interesting explicit conversion operators在这种情况下做正确的事情。

因此,您很少实际需要访问.Value属性。

这是所有你需要为你的投影:

var items = 
    from g in xDocument.Root.Descendants("Group").Elements("Entry") 
    select new 
    { 
     name = (string) g.Element("Name"), 
     id = (string) g.Element("ID") ?? "none", 
    }; 

而且如果你愿意在你的匿名类型使用的ID值作为一个整数:

var items = 
    from g in xDocument.Root.Descendants("Group").Elements("Entry") 
    select new 
    { 
     name = (string) g.Element("Name"), 
     id = (int?) g.Element("ID"), 
    }; 
3

在我使用的扩展方法类似的情况:

public static string OptionalElement(this XElement actionElement, string elementName) 
    { 
     var element = actionElement.Element(elementName); 
     return (element != null) ? element.Value : null; 
    } 

用法:

id = g.OptionalElement("ID") ?? "none" 
+0

非常整齐和整洁 – 2008-11-10 15:58:03

+0

我喜欢它 - 谢谢。 – itsmatt 2008-11-10 16:08:46

1

如何:

var items = from g in xDocument.Root.Descendants("Group").Elements("Entry") 
      let idEl = g.Element("ID") 
      select new 
      { 
       name = (string)g.element("Name").Value, 
       id = idEl == null ? "none" : idEl.Value; 
      }; 

如果这barfs,然后FirstOrDefault()等可能是有用的,否则只需使用扩展方法(如已经建议的那样)。