How do I do a deep copy of an element in LINQ to XML?

.NetLinq to-Xml

.Net Problem Overview


I want to make a deep copy of a LINQ to XML XElement. The reason I want to do this is there are some nodes in the document that I want to create modified copies of (in the same document). I don't see a method to do this.

I could convert the element to an XML string and then reparse it, but I'm wondering if there's a better way.

.Net Solutions


Solution 1 - .Net

There is no need to reparse. One of the constructors of XElement takes another XElement and makes a deep copy of it:

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

Here are a couple of unit tests to demonstrate:

[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);
}

Solution 2 - .Net

It looks like the ToString and reparse method is the best way. Here is the code:

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

Solution 3 - .Net

Lifted directly from C# 3.0 in a Nutshell:

When a node or attribute is added to an element (whether via functional construction or an Add method) the node or attribute's Parent property is set to that element. A node can have only one parent element: if you add an already parented node to a second parent, the node is automatically deep-cloned. In the following example, each customer has a separate copy of address:

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

This automatic duplication keeps X-DOM object instantiation free of side effects—another hallmark of functional programming.

Solution 4 - .Net

This should work:

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

Solution 5 - .Net

I do not believe there is an existing mechanism that allows you to perform a deep copy of an XNode style tree. I think you are left with two options.

  1. Do as you suggested an convert to a string and then back into a tree
  2. Write on yourself with a visitor pattern

The visitor pattern is certainly possible but it will take a good deal of work an testing. I think your best option is #1.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDaniel PlaistedView Question on Stackoverflow
Solution 1 - .NetJonathan MoffattView Answer on Stackoverflow
Solution 2 - .NetDaniel PlaistedView Answer on Stackoverflow
Solution 3 - .NetWonkoView Answer on Stackoverflow
Solution 4 - .NetChris CavanaghView Answer on Stackoverflow
Solution 5 - .NetJaredParView Answer on Stackoverflow