I have a new project where I need to generate a DOCX. My client has provided me with an existing DOCX where I need to replace some placeholders with some customer data from the database. As if this isn’t challenging enough, there are certain parts that are optional based on some conditions using the customer data. So I will have to provide some logic to totally omit some parts of the DOCX.
After way too much research and some POC’s, I’ve come across a new approach. I’ve saved the DOCX as a Word XML Document. This creates a big XML file with everything in it, even the images are encoded as base64. After doing that I copied the content of the XML file to a T4-template. Doing this allows me to add dynamic content based on the customer data and generate a Word XML Document in my code as a large string.
But now I’m stuck at creating a Docx again based on the Word XML Document string. I’ve tried using the OpenXml Sdk but can’t find any real documentation on how to do this. After some experimentation I ended up with the code below but it doesn’t parse XML (Data at the root level is invalid. Line 1, position 1).
As a second attempt, I tried out some suggestion from another post but this results in another exception (The XML has invalid content and cannot be constructed as an element. (Parameter 'outerXml'))
Is there a way to do this or should I just leave the T4-template and try another approach? Another problem with the T4-template is the size of some the images, it results in a long base64 string that just generates way too much lines. I guess I could replace the images with placeholders and swap them just before I create the XML...
public FileData CreateDocx(string title, string xml)
{
using (MemoryStream generatedDocument = new MemoryStream())
{
using (WordprocessingDocument package =
WordprocessingDocument.Create(generatedDocument, WordprocessingDocumentType.Document))
{
var mainPart = package.AddMainDocumentPart();
//First attempt
//new Document(xml).Save(mainPart);
var doc = new XmlDocument();
doc.LoadXml(xml);
new Document(doc.OuterXml).Save(mainPart);
}
return new FileData(title, generatedDocument.ToArray());
}
}