Insert images into document with shapes
Dear POI crew,
thank you for your work on POI. We might have found a bug that occurs when inserting images into Word documents that already contain shapes. There seems to be some kind of collision between the shapes' and the images' IDs. The problem only seems to occur after a certain amount of shapes is already present in the document.
POI seems to be able to open those documents just fine. However, when opening them in Word, we get the "do you want to recover this document" dialog.
We wrote a test that should illustrate the problem but we don't know how to fix it.
The duplication seems to be because of the "AlternatContent" (i.e. MSs way of not changing the spec, but still adding new types of content ...).
Can you try to add the following between opening the document and adding content? I am not 100% sure this is really the issue, so please verify that Microsoft Word can then read the document properly.
This can also be used as workaround if it is really fixing the issue.
for (XWPFParagraph paragraph : document.getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
XmlCursor cursor = run.getCTR().newCursor();
cursor.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' "
+ "declare namespace mc='http://schemas.openxmlformats.org/markup-compatibility/2006' "
+ "declare namespace wp='http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing' "
+ ".//mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/wp:docPr");
while(cursor.hasNextSelection()) {
cursor.toNextSelection();
XmlObject obj = cursor.getObject();
CTNonVisualDrawingProps docPr = CTNonVisualDrawingProps.Factory.parse(obj.xmlText());
document.getDrawingIdManager().reserve(docPr.getId());
}
}
}
See also https://stackoverflow.com/questions/68074154/are-there-mcalternatecontent-and-mcfallback-support-in-poi-xwpf-parser and https://stackoverflow.com/questions/46802369/replace-text-in-text-box-of-docx-by-using-apache-poi/46894499#46894499 for related discussions about "AlternateContent"
@centic9 , thanks for replying so fast.
We're testing the workaround in our project.
Another observation: "unable to open document" in Word only seems to happen when the shape is part of the footer. Word seems to be able to handle shapes in the document body better 🤔.
Hi @centic9 , we've done some more research and are using documents with shapes in the footer now. Applying the workaround as you posted it didn't fix the documents.
We also tried to add the footer paragraphs to the list of paragraphs the workaround iterates over. That didn't help either.
We also discarded our test assertions as the docPr values alone don't seem to cause the problem for word.
Ok, as said I am not sure if this will even make it work, but two things I see which might be off:
- It's important to do the "workaround()" immediately after loading the document, not at the end, otherwise avoiding duplicate ids will not work
- The current "workaround()" only looks at XPath ".//mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/wp:docPr", if the "docPr" is at a different location in the XML of the Paragraph/Run, another XPath/Cursor might be necessary to also find and "reserve()" those elements
Otherwise you will need to narrow down the problem as much as possible, both by making the document as simple a possible and the changes to the document as well. Unfortunately I cannot help much because I only have the online-version of Microsoft Word and this one seems to be able to load the document just fine.
Thanks again for helping.
I'm now running the workaround directly after loading the document. I've also changed the XPath to .//wp:docPr. The XPath worked when running "evaluate XPath" in IntelliJ on footer2.xml, but it didn't fix the broken documents.
I'll keep digging.