I had the same issue and of course I could not force user to do some extra stuff when composing their word document so I decided to just write an algo to scan the whole document for expressions appending run after run, inserting replacement value and remove expressions in the second run. In case other people may need it below is what I did. I got the class from somewhere so it may be familiar. I just added the method searchAndReplace()
package com.my.docx4j;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.Text;
public class Docx4j {
public static void main(String[] args) throws Docx4JException, IOException, JAXBException {
String filePath = "C:\\Users\\markamm\\Documents\\tmp\\";
String file = "Hello.docx";
Docx4j docx4j = new Docx4j();
WordprocessingMLPackage template = docx4j.getTemplate(filePath+file);
// MainDocumentPart documentPart = template.getMainDocumentPart();
List texts = getAllElementFromObject(
template.getMainDocumentPart(), Text.class);
searchAndReplace(texts, new HashMap(){
{
this.put("${abcd_efg.soanother_hello_broken_shit}", "Company Name here...");
this.put("${I_dont_know}", "Hmmm lemme see");
this.put("${${damn.right_lol}", "Gotcha!!!");
this.put("${one_here_and}", "Firstname");
this.put("${one}", "ChildA");
this.put("${two}", "ChildB");
this.put("${three}", "ChildC");
}
@Override
public String get(Object key) {
// TODO Auto-generated method stub
return super.get(key);
}
});
docx4j.writeDocxToStream(template, filePath+"Hello2.docx");
}
public static void searchAndReplace(List texts, Map values){
// -- scan all expressions
// Will later contain all the expressions used though not used at the moment
List els = new ArrayList();
StringBuilder sb = new StringBuilder();
int PASS = 0;
int PREPARE = 1;
int READ = 2;
int mode = PASS;
// to nullify
List toNullify = new ArrayList();
int[] currentNullifyProps = new int[4];
// Do scan of els and immediately insert value
for(int i = 0; i0)
for(int i = 0; i=floor && head<=ceil)){
nvalSB.append(c);
}
if(j>currentNullifyProps[3] && i>=currentNullifyProps[2]){
toNullify.remove(0);
if(toNullify.size()==0) {
currentNullifyProps = null;
continue;
}
currentNullifyProps = toNullify.get(0);
}
}
textElement.setValue(nvalSB.toString());
}
}
private WordprocessingMLPackage getTemplate(String name)
throws Docx4JException, FileNotFoundException {
WordprocessingMLPackage template = WordprocessingMLPackage
.load(new FileInputStream(new File(name)));
return template;
}
private static List getAllElementFromObject(Object obj,
Class> toSearch) {
List result = new ArrayList();
if (obj instanceof JAXBElement)
obj = ((JAXBElement>) obj).getValue();
if (obj.getClass().equals(toSearch))
result.add(obj);
else if (obj instanceof ContentAccessor) {
List> children = ((ContentAccessor) obj).getContent();
for (Object child : children) {
result.addAll(getAllElementFromObject(child, toSearch));
}
}
return result;
}
private void replacePlaceholder(WordprocessingMLPackage template,
String name, String placeholder) {
List texts = getAllElementFromObject(
template.getMainDocumentPart(), Text.class);
for (Object text : texts) {
Text textElement = (Text) text;
if (textElement.getValue().equals(placeholder)) {
textElement.setValue(name);
}
}
}
private void writeDocxToStream(WordprocessingMLPackage template,
String target) throws IOException, Docx4JException {
File f = new File(target);
template.save(f);
}
}