0
votes

So I need to generate a docx file for reporting purposes. This report contains text, tables and a lot of images. So far, I managed to add text and a table (and populate it based on the content of my xml using an xslt transform).

However, I am stuck on adding images. I found some examples of how to add images using C# but I don't think this is what I need. I need to format the document using my xslt and add the images in the right places (for instance in a table cell). Is it somehow possible to add a container using xslt which uses the filepath to display/embed the image similar to the <img> tag in html?
I know that the docx format is basically a zip containing a file structure and to embed the image I should add it to this file structure also.

Any examples or references are appreciated.

to give you an idea of my code:

XslCompiledTransform transform = new XslCompiledTransform();
transform.Load(xsltFile);

StringWriter stringWriter = new StringWriter();
XmlWriter xmlWriter = XmlWriter.Create(stringWriter);

transform.Transform(xmlFile, xmlWriter);

XmlDocument newWordContent = new XmlDocument();
newWordContent.LoadXml(stringWriter.ToString());

File.Copy(docXtemplate, outputFilename, true);

using (WordprocessingDocument myDoc = WordprocessingDocument.Open(outputFilename, true))
{
    MainDocumentPart mainPart = myDoc.MainDocumentPart;

    Body body = new Body(newWordContent.DocumentElement.InnerXml);
    DocumentFormat.OpenXml.Wordprocessing.Document document = new DocumentFormat.OpenXml.Wordprocessing.Document(body);
    document.Save(mainPart);
}

It basically replaces the body of an existing docx file. This enables me to use all the formatting, etc. The xslt file is generated by adjusting the document.xml file from the docx.

Update

Ok, so I figured out how to add an image to the docx file directory, see below

using (WordprocessingDocument myDoc = WordprocessingDocument.Open(outputFilename, true))
{
    MainDocumentPart mainPart = myDoc.MainDocumentPart;

    ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Png);
    using (FileStream stream = new FileStream(imageFile, FileMode.Open))
    {
       imagePart.FeedData(stream);
    }

    Body body = new Body(newWordContent.DocumentElement.InnerXml);
    DocumentFormat.OpenXml.Wordprocessing.Document document = new 
    DocumentFormat.OpenXml.Wordprocessing.Document(body);
    document.Save(mainPart);
}

This will add the image to the docx structure. I also checkt the relatioship and this is present in the 'document.xml.rels' file. When I take this id and use it in my xslt to add the image to the document (for testing), I do see an area where the image should be when opening with Word, however it says: cannot display image with the red cross.
A difference I do notice is that image which where in the orignal docx are saved in "word\media" while the added image with the code above is added in "media". Not sure if this is a problem

1
DOes this answer your question? Inserting images from XML to XSL document - stuartd
No this does not answer my question. They are creating an html page, I want to create a *.docx file. - Heimmot

1 Answers

0
votes

Ok, So I think I figured it out.

XslCompiledTransform transform = new XslCompiledTransform();
transform.Load(xsltFile);

StringWriter stringWriter = new StringWriter();
XmlWriter xmlWriter = XmlWriter.Create(stringWriter);

transform.Transform(xmlFile, xmlWriter);

XmlDocument newWordContent = new XmlDocument();
newWordContent.LoadXml(stringWriter.ToString());

using (WordprocessingDocument myDoc = WordprocessingDocument.Open(outputFilename, true))
{
    MainDocumentPart mainPart = myDoc.MainDocumentPart;

    ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Png, "imgId");
    using (FileStream stream = new FileStream(imageFile, FileMode.Open))
    {
       imagePart.FeedData(stream);
    }

    Body body = new Body(newWordContent.DocumentElement.InnerXml);
    DocumentFormat.OpenXml.Wordprocessing.Document document = new 
    DocumentFormat.OpenXml.Wordprocessing.Document(body);
    document.Save(mainPart);
}

The above code will add an image to your docx file structure with a specific id. You can use this id to refer to in your xsl transform. In the code example from my question I didn't set the id but used the one that was generated. However, each time you run this code the image will be added to the file with a new id resulting in a "not able to display" error. Not one of my sharpest moments;-).

For my use case I have to add multiple images to a large document so that code will be different but I think that based on the above code this can be achieved.