代码之家  ›  专栏  ›  技术社区  ›  Paul Mignard

linq to xml:处理不存在的节点?

  •  3
  • Paul Mignard  · 技术社区  · 16 年前

    这可能是一个简单的修复方法(可能是),但出于某种原因,我就是搞不清楚。

    所以,我有一些像这样的XML:

    XElement xml = XElement.Parse (
    @"<Alphabet>
         <a name="A" />
         <b name="B" />
         <d name="D" />
         <e name="E" />
    </Alphabet>");
    

    因此,在稍后的代码中,我引用了一个可能存在于其中,也可能不存在于其中的节点,如下所示:

    var name = (from b in xml.Descendants("c")
                select b.Attribute("name")).FirstOrDefault().Value;
    

    但当它不存在时,它不会返回空值或“”,而是抛出NullReferenceException:对象引用未设置为对象的实例。

    检查和查看linq查询中是否确实存在节点的最佳方法是什么?或者我需要检查它是否存在其他方法?

    4 回复  |  直到 16 年前
        1
  •  5
  •   Jon Skeet    16 年前

    好吧,您选择的是属性-所以只需使用:

    var nameAttribute = xml.Descendants("c").Select(b => b.Attribute("name"))
                                            .FirstOrDefault();
    if (nameAttribute != null)
    {
        string name = nameAttribute.Value;
    }
    else
    {
        // Whatever...
    }
    

    (我把它从一个查询表达式改为点表示法,因为查询很简单——查询表达式语法实际上并没有为您购买任何东西。)

    这个解决方案的一个问题是:它没有区分存在一个“c”元素,但是它没有“name”属性,并且首先没有一个“c”元素。你需要能够分辨出区别吗?

        2
  •  4
  •   mhenrixon    16 年前

    我创建了扩展方法来实现这一点。

    public static string GetAttributeValue(this XElement element, string attributeName)
    {
        XAttribute attribute = element.Attribute(attributeName);
        return attribute != null ? attribute.Value : string.Empty;
    }
    
    public static string GetElementValue(this XElement element)
    {
        return element != null ? element.Value : string.Empty;
    }
    
    public static string GetElementValue(this XElement element, string elementName)
    {
        XElement child = element.Element(elementName);
        return child != null ? child.Value : string.Empty;
    }
    
        3
  •  1
  •   dtb    16 年前

    FirstOrDefault 退货 null XAttribute 你可以把它铸造成 string 要获取值:

    var name = (string)((from b in xml.Descendants("c")
                         select b.Attribute("name")).FirstOrDefault());
    

    var name = (string)xml.Descendants("c")
                          .Select(b => b.Attribute("name"))
                          .FirstOrDefault();
    
        4
  •  0
  •   bruno conde    16 年前

    你可以这样做:

    var name = (from b in xml.Descendants("c")
                select b.Attribute("name").Value).FirstOrDefault();
    

    或者如果你真的需要元素:

    var name = (from b in xml.Descendants("c")
                select b.Attribute("name")).FirstOrDefault();
    
    if (name != null)
    {
        // your logic ...
    }