In this tutorial we'll quickly review how you can copy an XML node (XmlNode) from one XML document to another. The most important methods we're going to use are AppendChild() and ImportNode().
Very often, your first try of copying a node from an XML file to another will result in the following error:
The node to be inserted is from a different document context.
That’s because you are using AppendChild() incorrectly. First you need to create a new node using ImportNode() and then add that node to the document.
In the example project attached to this tutorial and in the source code below we copy a node named CopyMe (<CopyMe>) from SourceDoc.xml to DestinationDoc.xml. Here’s how the two XML documents look like:
SourceDoc.xml:
<SourceRoot>
<SampleNode />
<CopyMe />
<SomeOtherNode />
</SourceRoot>
DestinationDoc.xml
<DestinationRoot>
<ExistingNode />
<SomeOtherNode />
</DestinationRoot>
Before we start, make sure you add the following using directive:
using System.Xml;
First we load the source XML file into an XmlDocument object:
// Open the reader with the source XML file
XmlTextReader myReader = new XmlTextReader("SourceDoc.xml");
// Load the source of the XML file into an XmlDocument
XmlDocument mySourceDoc = new XmlDocument();
// Load the source XML file into the first document
mySourceDoc.Load(myReader);
// Close the reader
myReader.Close();
Then we load the destination XML file into a different XmlDocument:
// Open the reader with the destination XML file
myReader = new XmlTextReader("DestinationDoc.xml");
// Load the source of the XML file into an XmlDocument
XmlDocument myDestDoc = new XmlDocument();
// Load the destination XML file into the first document
myDestDoc.Load(myReader);
// Close the reader
myReader.Close();
Then we need to store the root node of the destination document into an XmlNode, because we will later append the copy of the node to it. Next we store the node into an XmlNode (nodeOrig) and its copy into nodeDest. Using AppendChild() we append the node into the destination document.
The obvious thing to do might not be to use ImportNode() like I did here, so you might say “why can’t
I use AppendChild() directly on nodeOrig instead of creating a copy of nodeOrig and putting it into nodeDest?”. Well, if you do that and use AppendChild(nodeOrig) you will get the error “The node to be inserted is from a different document context“. And you don’t want that.
So to prevent this error you need to use ImportNode(nodeOrig, true). Also, if you’re wondering what the true parameter is for – it specifies wether or not to perform a deep import (including child nodes) or not.
// Store the root node of the destination document into an XmlNode
// The 1 in ChildNodes[1] is the index of the node to be copied (where 0 is the first node)
XmlNode rootDest = myDestDoc["DestinationRoot"];
// Store the node to be copied into an XmlNode
XmlNode nodeOrig = mySourceDoc["SourceRoot"].ChildNodes[1];
// Store the copy of the original node into an XmlNode
XmlNode nodeDest = myDestDoc.ImportNode(nodeOrig, true);
// Append the node being copied to the root of the destination document
rootDest.AppendChild(nodeDest);
Finally, we write the changes to the destination XML file:
// Open the writer
XmlTextWriter myWriter = new XmlTextWriter("DestinationDoc.xml", Encoding.UTF8);
// Indented for easy reading
myWriter.Formatting = Formatting.Indented;
// Write the file
myDestDoc.WriteTo(myWriter);
// Close the writer
myWriter.Close();