<b>
<c>
<z> Wally </z>
<w> whatever </w>
</c>
<d>
<z> anotherValue </z>
</d>
<e> idValue </e>
</b>
class Example {
public string Id {get; set;}
public string name {get; set;}
}
假设我们有上面的xml和类。我试图使用LinQ到Xml从xml创建一个对象。
我可以通过以下方式实现这一目标:
var doc = XDocument.Load(xmlPath);
var root = doc.Root;
var anExample = new Example()
{
Id = root.Element("e").Value,
name = root.Element("c").Element("z").Value
};
到目前为止,问题是'c'和'z'标签是可选的。你可以没有'c'或'c'没有'z'。 然后我会发现自己检查每个标记是否为null,以避免在null对象上调用Element方法和Value属性。 我的意思是:
var doc = XDocument.Load(xmlPath);
var root = doc.Root;
var anExample = new Example(){ Id = root.Element("e").Value };
var c = root.Element("c")
if(c != null) {
var z = c.Element("z");
if( z != null)
anExample.name = z.Value;
}
随着嵌套级别的增加,事情变得更糟。我想大多数人都有更好的方式去做我想做的事。
答案 0 :(得分:1)
您可以使用C# 6.0 null-conditional operator确保调用链中的所有项都不为空:
// C# 6 or higher:
string value = doc.Root?.Element("c")?.Element("z")?.Value;
如果仅存在所有给定元素,则此表达式的结果将具有值,否则将为null
。
另一种方法是使用System.Xml.XPath
命名空间中的XPath扩展方法来查找元素。如果您使用C#6甚至更旧版本更合适,因为它没有空条件运算符看起来很好:
// C# 6 or higher:
string value = doc.Root.XPathSelectElement("./c/z")?.Value;
// C# 5 or lower:
var element = doc.Root.XPathSelectElement("./c/z");
if (element != null)
{
string value = element.Value;
}
结果将是相同的,因为如果元素不存在,XPathSelectElement
将返回null
。
答案 1 :(得分:0)
你应该尝试留在IEnumerable
的LINQ世界,直到最后一刻。
这意味着使用Elements
而不是Element
- 如果元素丢失,这将返回一个空序列。
最后,您可以调用SingleOrDefault
来获取结果元素,如果缺少其中一个元素,则可以调用null。
请注意,explicit conversion operators可以将元素转换为各种类型 - 当您需要转换为string
之外的其他内容时,这可能很有用,并且还可以处理元素为null的情况。
var name = (string) root.Elements("c").Elements("z").SingleOrDefault()