我正在使用对XElement.Element()
方法的一系列调用来深入研究XML文档并提取属性的值:
XElement root = ...;
XNamespace ns = "...";
var firstName =
root
.Element(ns + "Employee")
.Element(ns + "Identity")
.Element(ns + "Name")
.Attribute(ns + "FirstName");
但是,由于传入文档尚未经过模式验证,如果任何预期的中间元素不存在,则格式错误的文档可能会导致NullReferenceException
。
有没有办法避免这种风险,同时保持代码简洁?
我可以将上面的代码包装在NullReferenceException
的处理程序中但是这感觉不对,并且也没有具体指出失败发生的位置。构建信息性错误消息将是手动,繁琐,容易出错和维护危险。
我是否应该使用XPath,这样我可以检查null返回,然后轻松构造一条错误消息,指示XPath表达式无法解析?
答案 0 :(得分:7)
一种选择是使用Elements()
而不是Element()
- 如果找不到该元素,将产生一个空序列。使用Extensions中的扩展方法,您可以从元素序列到元素序列 - 对于属性也是如此。所以:
var firstName =
root
.Elements(ns + "Employee")
.Elements(ns + "Identity")
.Elements(ns + "Name")
.Attributes(ns + "FirstName")
.FirstOrDefault();
两个片段之间存在差异,请注意 - 这将找到第一个匹配属性,即使它来自(比如说)第二个Employee中第三个Identity元素中的第一个Name元素元件。这对您来说可能是也可能不是问题。
(只是为了检查,你肯定需要属性上的命名空间吗?与元素不同,属性不会继承“默认”命名空间。在命名空间上使用属性比在元素上使用属性更少。)
答案 1 :(得分:1)
您可以定义en extension方法来包装空值检测。像这样的东西,例如:
public static class XmlExtender
{
public static XAttribute AttributeOrDefault(this XElement el, XName name, string defValue)
{
var v = el.Attribute(name);
return v == null ? new XAttribute(name, defValue) : v;
}
public static string AttributeValue(this XElement el, XName name, string defValue)
{
var v = el.Attribute(name);
return v == null ? defValue : v.Value;
}
}
然后可以像这样使用:
var firstName = root.ELement("elname")
.AttributeOrDefault("attrName", "N/A").Value;
或者这个:
var firstName = root.Element("elname")
.AttributeValue("attrName", "N/A");