LINQ to XML
deep copy
C#
XML manipulation
programming tutorial

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

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In LINQ to XML, a deep copy of an XElement is easy: create a new XElement from the existing one. The constructor copies the element name, attributes, and all descendant nodes, giving you a separate XML tree that can be modified independently.

This matters because XML nodes have a parent relationship. If you try to add the same XElement instance into another location, you are moving that node, not cloning it. A constructor-based copy is the normal fix.

Create a Deep Copy with the XElement Constructor

The standard pattern is:

csharp
1using System;
2using System.Xml.Linq;
3
4XElement original = new XElement("book",
5    new XAttribute("id", 10),
6    new XElement("title", "Practical XML"),
7    new XElement("author", "A. Chen")
8);
9
10XElement copy = new XElement(original);
11
12copy.Element("title")!.Value = "Copied Book";
13
14Console.WriteLine(original);
15Console.WriteLine(copy);

The copy variable now points to a new tree. Changing copy does not affect original.

Why This Counts as a Deep Copy

A deep copy duplicates:

  • the element itself
  • attributes
  • child elements
  • text nodes and other descendant nodes

That means nested XML is copied all the way down:

csharp
1XElement source = XElement.Parse("""
2<order id="42">
3  <customer>
4    <name>Ava</name>
5  </customer>
6  <items>
7    <item sku="A1" />
8    <item sku="B2" />
9  </items>
10</order>
11""");
12
13XElement clonedOrder = new XElement(source);
14clonedOrder.Element("customer")!.Element("name")!.Value = "Mina";

After this change, the original source still contains Ava, because the nested nodes were copied rather than shared.

Avoid Moving the Original by Accident

This is the mistake that usually triggers the question:

csharp
1XElement item = new XElement("item", "Laptop");
2XElement listA = new XElement("listA", item);
3XElement listB = new XElement("listB");
4
5listB.Add(item);

After listB.Add(item), the element is removed from listA and moved into listB. XML nodes in LINQ to XML cannot belong to two parents at once.

If you need the same structure in both places, clone it:

csharp
listB.Add(new XElement(item));

That leaves the original node in listA and inserts a copied version into listB.

Copy Whole Documents or Collections

The same pattern applies to XDocument:

csharp
1XDocument originalDoc = XDocument.Parse("""
2<catalog>
3  <book id="1" />
4</catalog>
5""");
6
7XDocument copiedDoc = new XDocument(originalDoc);

And if you want copies of many sibling elements, project them explicitly:

csharp
var copiedItems = source.Elements("item")
    .Select(element => new XElement(element))
    .ToList();

This is useful when extracting parts of one document into another without disturbing the source tree.

What Does Not Come Along Automatically

The XML content is copied, but you should not think of the clone as a complete duplicate of every piece of runtime state. If your application associates extra state outside the XML tree, that is your responsibility to copy separately.

For most everyday LINQ to XML work, the constructor copy is exactly what you want because it preserves document structure and values while giving you independent nodes.

Common Pitfalls

  • Adding the same XElement to a second parent and expecting a clone. LINQ to XML moves the node instead.
  • Doing a constructor copy too late, after the original element has already been removed or modified elsewhere.
  • Confusing a deep XML copy with copying unrelated application metadata attached outside the XML tree.
  • Reusing references to child elements from the original tree after cloning. Children from the original and children from the clone are different objects.
  • Copying large XML trees unnecessarily when a query over the original document would be enough.

Summary

  • Use new XElement(existingElement) to deep copy an XML element in LINQ to XML.
  • The copy includes attributes and all descendant nodes.
  • Adding an existing node to another parent moves it instead of cloning it.
  • Use the same constructor-based approach for nested elements or projected collections.
  • Clone only when you need structural independence, not just read-only access.

Course illustration
Course illustration

All Rights Reserved.