使用 LINQ to XML 时避免暴露 NullReferenceException
我正在使用对 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 来代替,这样我就可以检查空返回,然后轻松构造一个错误消息表明无法解析 XPath 表达式?
I am using a chain of calls to the XElement.Element()
method to drill down into an XML document and pull out the value of an attribute:
XElement root = ...;
XNamespace ns = "...";
var firstName =
root
.Element(ns + "Employee")
.Element(ns + "Identity")
.Element(ns + "Name")
.Attribute(ns + "FirstName");
However, since the incoming document has not been schema validated it is possible that a malformed document will cause a NullReferenceException
if any of the expected intermediate elements does not exist.
Is there a way to avoid this risk, whilst keeping the code succinct?
I can wrap the code above in a handler for NullReferenceException
however this feels wrong, and would also not specifically indicate where the failure occurred. Constructing an informative error message would be manual, tedious, error prone, and a maintenance hazard.
Should I be using XPath instead, that way I can check for a null return and then easily construct an error message indicating that the XPath expression could not be resolved?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
一种选择是使用
Elements()
而不是Element()
- 如果找不到元素,这将产生一个空序列。使用扩展中的扩展方法,您可以从元素序列到元素序列 - 属性也是如此。所以:请注意,两个片段之间存在差异 - 这将找到第一个匹配属性,即使它来自(例如)第二个 Employee 元素中的第三个 Identity 元素中的第一个 Name 元素。这对您来说可能是问题,也可能不是问题。
(只是检查一下,您确实需要属性上的命名空间吗?与元素不同,属性不会继承“默认”命名空间。在命名空间上使用属性比在元素上使用属性更罕见。)
One option is to use
Elements()
instead ofElement()
- which will yield an empty sequence if the element isn't found. Using the extension methods in Extensions, you can go from a sequence of elements to a sequence of elements - and the same for attributes. So:There is a difference between the two snippets, mind you - this will find the first matching attribute even if it comes from (say) the first Name element within the third Identity element within the second Employee element. That may or may not be an issue for you.
(Just to check, do you definitely need the namespace on the attribute? Unlike elements, attributes don't inherit a "default" namespace. It's rarer to use attributes on namespaces than on elements.)
您可以定义扩展方法来包装空检测。像这样的东西,例如:
然后可以像这样使用:
或这样:
You can define en extension method to wrap the null detection. Something like this, for instance:
which can then be used like this:
or this: