将XDocument.Root添加至另一XElement未达预期效果的问题
为什么添加XDocument的Root元素到另一个XElement后,原元素的Parent仍为null?
我完全懂你的困惑——这个行为看起来有点反直觉,但其实是LINQ to XML的设计逻辑导致的,咱们一步步拆解清楚:
先看你的代码核心问题点
你的测试代码如下:
XDocument x=new XDocument(new XElement("asd")); XElement root=x.Root; XElement parent=new XElement("parent"); Console.WriteLine(root.Parent?.Name??"null"); // 输出null parent.Add(root); Console.WriteLine(root.Parent?.Name??"null"); // 还是输出null
原因1:XDocument的Root元素的Parent属性本身就是null
XDocument.Root返回的顶级元素,它的父容器是XDocument对象,但XElement.Parent属性的定义是:只返回父级的XElement节点。因为XDocument不是XElement类型,所以root.Parent从一开始就是null,这是符合设计的正常现象。
原因2:添加已有归属的元素时,LINQ to XML会自动克隆副本
当你调用parent.Add(root)时,root已经属于一个XDocument的一部分了。LINQ to XML不允许同一个XElement实例同时属于两个不同的XML树(比如一个XDocument和一个XElement),所以它不会把原来的root移动到parent里,而是创建一个完全相同的副本添加到parent中。
原来的root依然留在原来的XDocument里,它的Parent自然还是null。你可以用下面的代码验证这一点:
// 检查parent的第一个子元素和原root是不是同一个实例 Console.WriteLine(object.ReferenceEquals(root, parent.Elements().First())); // 输出:False,说明是两个完全不同的对象
怎么让原元素的Parent变成parent?
如果你想让原来的root真正成为parent的子元素,需要先把它从原来的XDocument中移除:
XDocument x=new XDocument(new XElement("asd")); XElement root=x.Root; XElement parent=new XElement("parent"); root.Remove(); // 先从XDocument中移除root,解除它的归属 parent.Add(root); Console.WriteLine(root.Parent?.Name??"null"); // 现在会输出"parent"
这样操作后,root不再属于原来的XDocument,就可以被直接添加到parent中,它的Parent属性也会正确指向parent了。
内容的提问来源于stack exchange,提问作者alessio bortolato
相关产品推荐
相关产品推荐

