Writing into same OpenXmlPart being read

390 Views Asked by At

Is there a way write into the same OpenXmlPart that is being read by an OpenXmlPartReader? I'm going to detect things with the reader and potentially write things in place with an OpenXmlWriter. Here is a sample that does not work:

var ms = new MemoryStream();
var doc = WordprocessingDocument.Create(ms, WordprocessingDocumentType.Document);

MainDocumentPart part = doc.AddMainDocumentPart();
part.Document = new Document(new Body(new Paragraph(), new Paragraph()));
doc.Save();

var stream = part.GetStream();
var reader = OpenXmlReader.Create(stream);
var writer = OpenXmlWriter.Create(stream);

reader.Read(); // read w:document
reader.ReadFirstChild(); // read w:body
reader.ReadFirstChild(); // read 1st w:p
writer.WriteElement(new Table()); // try to insert w:tbl

doc.Save(); // observe only the 2 paragraphs in the `w:body`.

It looks like under the covers the Open XML SDK is using XmlReader and XmlWriter under the covers, so perhaps there is a way to synchronize those?

1

There are 1 best solutions below

0
On

So it appears that there is no way to synchronize the OpenXmlReader and OpenXmlWriter out of the box.

What I ended up doing was cloning the original document, clearing out the parts and writing into them conditionally, while reading out of the OpenXmlReader.

Here is a simplified model of what I did:

var ms = new MemoryStream();
var inputDoc = WordprocessingDocument.Create(ms, WordprocessingDocumentType.Document);

MainDocumentPart inputMainPart = inputDoc.AddMainDocumentPart();
inputMainPart.Document = new Document(new Body(new Paragraph(), new Paragraph()));
input.Save();

var outputDoc = input.Clone();
outputDoc.RemovePart(outputDoc.MainDocumentPart);
var outputMainPart = outputDoc.AddMainDocumentPart();


var reader = OpenXmlReader.Create(inputMainPart);
var writer = OpenXmlWriter.Create(outputMainPart);
// write body/document

reader.Read(); // read w:document
reader.ReadFirstChild(); // read w:body
reader.ReadFirstChild(); // read 1st w:p

do {
    writer.WriteElement(new Table()); // insert w:tbl
    writer.WriteElement(reader.LoadCurrentElement());
} while(reader.ReadNextSibling());
doc.Save(); // observe only the 2 paragraphs in the `w:body`.