wordpress hit counter
Re: Copy OpenXmlElement between documents - Open XML SDK 2.0 - Development Tools - OpenXML Developer

Re: Copy OpenXmlElement between documents

Development Tools

Discussions about working with Open XML using a wide range of development tools

Copy OpenXmlElement between documents

  • rated by 0 users
  • This post has 4 Replies |
  • 3 Followers
  • Hi,

    I have two Word documents (WordprocessingDocument), and I want to replace the contents of an element in the first with the contents in the body of the second one.

    This is what I'm doing right now:

    var docA = WordprocessingDocument.Open(docAPath, true);
    var docB = WordprocessingDocument.Open(docBPath, true);

    var containerElement = docA.MainDocumentPart.Document.Body
    .Descendants<SdtBlock>()
    .FirstOrDefault(sdt => sdt.SdtProperties.Descendants<SdtAlias>().Any(alias => alias.Val == containerElementName))
    .SdtContentBlock;

    var elementsToCopy = docB.MainDocument.Part.Document.Body.ChildElements.Where(e => e.LocalName != "sectPr"));

    containerElement.RemoveAllChildren();
    containerElement.Append(elementsToCopy);


    Basically I get the container (an SdtBlock) from the first document using its alias to identify it, then get all the children of the second element (removing the SectionProperties which I don't want to copy) and then try to add those to the container element.

    The problem is that I'm getting this exception:

    Cannot insert the OpenXmlElement "newChild" because it is part of a tree.

    When I invoke the last line on that code (the Append).

    Any ideas on how can I achieve what I want?

    Thanks
  • Hi

    Just a small tweak needed for your code - you need to clone the OpenXmlElements you're appending so they're not tied into their existing tree:

    var containerElement = docA.MainDocumentPart.Document.Body.Descendants<SdtBlock>().FirstOrDefault(
        sdt => sdt.SdtProperties.Descendants<Alias>().Any(alias => alias.Val == containerElementName))
        .SdtContentBlock;

    IEnumerable<OpenXmlElement> elementsToCopy = docB.MainDocumentPart.Document.Body.ChildElements.Where(e => e.LocalName != "sectPr");

    List<OpenXmlElement> clonedElements = new List<OpenXmlElement>();

    foreach (OpenXmlElement element in elementsToCopy)
    {
        clonedElements.Add((OpenXmlElement)element.Clone());
    }


    containerElement.RemoveAllChildren();
    containerElement.Append(clonedElements);


  • Hi,

    Thanks a lot for your answer, that's exactly what I was looking for.

    Regards

    P.S.
    How do you get the &lt; character in your posts?
  • Great, glad it helped :)

    I'm not sure why the < characters are working for me - I'm using Firefox but not sure if that's why
  • This is what i am doing right now

    foreach (var objField in objMainDoc.Descendants<SimpleField>())

               {

                   string strFieldName = GetFieldName(objField);

                   if (!string.IsNullOrEmpty(strFieldName))

                   {

                       if (values.ContainsKey(strFieldName) && !string.IsNullOrEmpty(values[strFieldName]))

                       {

                           string strRunProp = null;

                           if (objField != null)

                           {

                               foreach (RunProperties objRP in objField.Descendants<RunProperties>())

                               {

                                   strRunProp = objRP.OuterXml;

                                   break;

                               }

                           }

                           Run objRun = new Run();

                           if (!string.IsNullOrEmpty(strRunProp))

                           {

                               objRun.Append(new RunProperties(strRunProp));

                           }

                           //add the text to the place holder

                           //objRun.Append(new Text(values[strFieldName]));

                           objRun.Append(new RunProperties(tbl));

                           //replace the merge field with the value

                         //  objField.Parent.ReplaceChild<SimpleField>(objRun, objField);

                         //  objField.Parent.ReplaceChild<SimpleField>(tbl , objField);

                       }

                   }

               }

    i want to insert table into perticular fields in word docx file.

    The problem is that I'm getting this exception:

    Cannot insert the OpenXmlElement "newChild" because it is part of a tree.

Page 1 of 1 (5 items)