I am using Apache POI to replace words of docx. For a normal paragraph, I success to use XWPFParagraph and XWPFRun to replace the words. Then I tried to replace words in text box. I referenced this https://stackoverflow.com/a/25877256 to get text in text box. I success to print the text in console. However, I failed to replace words in text box. Here are some of my codes:
for (XWPFParagraph paragraph : doc.getParagraphs()) {
XmlObject[] textBoxObjects = paragraph.getCTP().selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' declare namespace wps='http://schemas.microsoft.com/office/word/2010/wordprocessingShape' .//*/wps:txbx/w:txbxContent");
for (int i =0; i < textBoxObjects.length; i++) {
XWPFParagraph embeddedPara = null;
try {
XmlObject[] paraObjects = textBoxObjects[i].
selectChildren(
new QName("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "p"));
for (int j=0; j<paraObjects.length; j++) {
embeddedPara = new XWPFParagraph(CTP.Factory.parse(paraObjects[j].xmlText()), paragraph.getBody());
List<XWPFRun> runs = embeddedPara.getRuns();
for (XWPFRun r : runs) {
String text = r.getText(0);
if (text != null && text.contains(someWords)) {
text = text.replace(someWords, "replaced");
r.setText(text, 0);
}
}
}
} catch (XmlException e) {
//handle
}
}
}
I think the problem is that I created a new XWPFParagraph embeddedPara and it's replacing the words of embeddedPara but not the origin paragraph. So after I write in a file, the words still not change.
How can I read and replace the words in the text box without creating a new XWPFParagraph?
The problem occurs because the
Word
text boxes may be contained in multiple differentXmlObjects
dependent of theWord
version. ThoseXmlObjects
may also be in very different name spaces. So theselectChildren
cannot following the name space route and so it will return aXmlAnyTypeImpl
.What all text box implementatrion have in common is that their runs are in the path
.//*/w:txbxContent/w:p/w:r
. So we can using aXmlCursor
which selects that path. Then we collect all selectedXmlObjects
in aList<XmlObject>
. Then we parseCTR
s from those objects, which are of course onlyCTR
s outside the document context. But we can creatingXWPFRuns
from those, do the replacing there and thenset
the XML content of thoseXWPFRuns
back to the objects. After this we have the objects containing the replaced content.Example: