如何在LINQ to XML中做一个元素的深层副本?

我想做一个LINQ to XML XElement的深层副本。 我想这样做的原因是文档中有一些节点需要创build(在同一文档中)的修改副本。 我没有看到一个方法来做到这一点。

我可以将元素转换为XMLstring,然后重新parsing它,但是我想知道是否有更好的方法。

没有必要重新分析。 XElement的一个构造函数接受另一个XElement,并对其进行了深层次的复制:

XElement original = new XElement("original"); XElement deepCopy = new XElement(original); 

这里有几个unit testing来演示:

 [TestMethod] public void XElementShallowCopyShouldOnlyCopyReference() { XElement original = new XElement("original"); XElement shallowCopy = original; shallowCopy.Name = "copy"; Assert.AreEqual("copy", original.Name); } [TestMethod] public void ShouldGetXElementDeepCopyUsingConstructorArgument() { XElement original = new XElement("original"); XElement deepCopy = new XElement(original); deepCopy.Name = "copy"; Assert.AreEqual("original", original.Name); Assert.AreEqual("copy", deepCopy.Name); } 

它看起来像ToString和重parsing方法是最好的方法。 这里是代码:

 XElement copy = XElement.Parse(original.ToString()); 

简单地从C#3.0中摘取 :

当一个节点或属性被添加到一个元素(无论是通过函数构造还是一个Add方法),节点或属性的Parent属性被设置为该元素。 一个节点只能有一个父元素:如果将一个已经父节点的节点添加到另一个父节点,则该节点将被自动深度克隆。 在以下示例中,每个客户都有一个单独的地址副本:

 var address = new XElement ("address", new XElement ("street", "Lawley St"), new XElement ("town", "North Beach") ); var customer1 = new XElement ("customer1", address); var customer2 = new XElement ("customer2", address); customer1.Element ("address").Element ("street").Value = "Another St"; Console.WriteLine ( customer2.Element ("address").Element ("street").Value); // Lawley St 

这种自动复制保持了X-DOM对象实例化的副作用 – 函数式编程的另一个标志。

这应该工作:

 var copy = new XElement(original.Name, original.Attributes(), original.Elements() ); 

我不相信有一个现有的机制,允许您执行一个XNode风格树的深层副本。 我想你有两个select。

  1. 按照你的build议转换成string,然后回到树中
  2. 用访客模式写下你自己

访客模式当然是可能的,但是这需要大量的工作来进行testing。 我认为你最好的select是#1。