在分析XDocument时处理null XElements



有更好的方法来做这样的事情吗:

private XElement GetSafeElem(XElement elem, string key)
{
    XElement safeElem = elem.Element(key);
    return safeElem ?? new XElement(key);
}
private string GetAttributeValue(XAttribute attrib)
{
    return attrib == null ? "N/A" : attrib.Value;
}
var elem = GetSafeElem(elem, "hdhdhddh");
string foo = GetAttributeValue(e.Attribute("fkfkf"));
//attribute now has a fallback value

解析XML文档中的元素/属性值时?在某些情况下,在执行以下操作时可能找不到元素:

string foo (string)elem.Element("fooelement").Attribute("fooattribute").Value

因此会发生对象引用错误(假设找不到元素/属性)。尝试访问元素值时也是如此

我只会使用扩展方法。这是一样的,但更漂亮:

public static XElement SafeElement(this XElement element, XName name)
{
    return element.Element(name) ?? new XElement(name);
}
public static XAttribute SafeAttribute(this XElement element, XName name)
{
    return element.Attribute(name) ?? new XAttribute(name, string.Empty);
}

然后你可以做:

string foo = element.SafeElement("fooelement").SafeAttribute("fooattribute").Value;

在C#6.0中,可以使用一元Null条件运算符?.在你的例子中应用它之后,它看起来像这样:

string foo = elem.Element("fooelement")?.Attribute("fooattribute")?.Value;

若fooelement或fooattribute不存在,则整个表达式将导致null。您可以在标题为Null条件运算符的部分阅读更多内容。

不确定这是一种更好的方法,但我在CodeProject的一篇文章中看到了它,并认为它可能是一种有用的方法。

这是一个使用"With"扩展方法的一元解决方案:

public static TResult With<TInput, TResult>(this TInput o, 
       Func<TInput, TResult> evaluator)
       where TResult : class where TInput : class
{
  if (o == null) return null;
  return evaluator(o);
}

和返回扩展方法:

public static TResult Return<TInput,TResult>(this TInput o, 
       Func<TInput, TResult> evaluator, TResult failureValue) where TInput: class
{
  if (o == null) return failureValue;
  return evaluator(o);
}

将它们结合在一起,您的查询可能看起来像这样:

var myElement = element.With(x => x.Element("FooElement")).Return(x => x.Attribute("FooAttribute").Value, "MyDefaultValue")

不确定它是否比使用简单的扩展方法更漂亮,这些家伙在之前的帖子中已经建议过了,但它有点通用,是一种很好的方法IMO

CodeProject-链接的空检查和Maybe monad

用这种方法试试;

public static string TryGetElementValue(this XElement parentEl, string elementName, string defaultValue = null) 
{
    var foundEl = parentEl.Element(elementName);
    if(foundEl != null)
    {
     return foundEl.Value;
    }
else
{
     return defaultValue;
}
}

然后像这样更改代码:

select new News()
                {
                    id = noticia.TryGetElementValue("IdNoticia"),
                    published = noticia.TryGetElementValue("Data"),
                    title = noticia.TryGetElementValue("Titol"),
                    subtitle = noticia.TryGetElementValue("Subtitol"),
                    thumbnail = noticia.TryGetElementValue("Thumbnail", "http://server/images/empty.png")
                };

最新更新