Wednesday, July 8, 2009

How to get around OpenXML error: Can not replace the OpenXmlElement "newChild" because it is part of a tree

I was recently working on a MS Word doc generation project and kept getting this error.

It took me a while to figure out the source of the problem, but it made total sense...
When you are a building a document tree (example below), you are creating new elements like

var myRun = new Run(new Text("reusable text"));

var myParagraph = new Paragraph();


The 3rd line above ties in that Run object into the Paragraph object, so if you try to reuse the myRun object by appending it somewhere else - you will get this error.

I also tried creating a new Run() object using the old one as the object initializer:

var myRun2 = new Run(myRun);

That will throw the same error.
Why? Because the above line copies instantiates myRun2 with the reference of the myRun object so when you try to Append it elsewhere, you will get the error because it's technically the same object.

There is a very handy property that most OpenXML elements have - OuterXml. The other handy thing about it - it's in most class constructors so it can be used to instantiate an object.
In lamens terms, instead of

var myRun2 = new Run(myRun);


var myRun2 = new Run(myRun.OuterXml);

Sample tree:
  • SdtBlock
  • - Paragraph
  • ----Run
  • ------Text
  • ----Run
  • ------Break
  • ----Run
  • ------Text