package cn.flightfeather.supervision.docx4j.simpleDemo;
|
|
import org.docx4j.TraversalUtil;
|
import org.docx4j.XmlUtils;
|
import org.docx4j.finders.RangeFinder;
|
import org.docx4j.jaxb.Context;
|
import org.docx4j.model.fields.merge.DataFieldName;
|
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
|
import org.docx4j.wml.*;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
|
/**
|
* Replace text between w:bookmarkStarts and corresponding w:bookmarkEnds
|
* with specified data, matching on bookmark's @w:name
|
*
|
*/
|
public class BookmarksReplaceWithText {
|
|
/*
|
* Requirements:
|
* - bookmarkStart and End must be in the same paragraph
|
* - no attempt is made to check whether the start of some other bookmark is
|
* in that range. If it is, it will get deleted!
|
* - no attempt is made to preserve the rPr
|
* - mdp only right now
|
*/
|
|
protected static Logger log = LoggerFactory.getLogger(BookmarksReplaceWithText.class);
|
|
private static boolean DELETE_BOOKMARK = false;
|
|
private static org.docx4j.wml.ObjectFactory factory = Context.getWmlObjectFactory();
|
|
|
public static void main(String[] args) throws Exception {
|
|
Map<DataFieldName, String> map = new HashMap<DataFieldName, String>();
|
map.put( new DataFieldName("bm1"), "whale shark");
|
|
|
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage
|
.load(new java.io.File(System.getProperty("user.dir")
|
+ "/bm1.docx"));
|
MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
|
|
// Before..
|
// System.out.println(XmlUtils.marshaltoString(documentPart.getJaxbElement(), true, true));
|
|
org.docx4j.wml.Document wmlDocumentEl = (org.docx4j.wml.Document) documentPart
|
.getJaxbElement();
|
Body body = wmlDocumentEl.getBody();
|
|
BookmarksReplaceWithText bti = new BookmarksReplaceWithText();
|
|
bti.replaceBookmarkContents(body.getContent(), map);
|
|
// After
|
// System.out.println(XmlUtils.marshaltoString(documentPart.getJaxbElement(), true, true));
|
|
// save the docx...
|
wordMLPackage.save(new java.io.File(System.getProperty("user.dir") + "/OUT_BookmarksTextInserter.docx"));
|
}
|
|
private void replaceBookmarkContents(List<Object> paragraphs, Map<DataFieldName, String> data) throws Exception {
|
|
RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
|
new TraversalUtil(paragraphs, rt);
|
|
for (CTBookmark bm : rt.getStarts()) {
|
|
// do we have data for this one?
|
if (bm.getName()==null) continue;
|
String value = data.get(new DataFieldName(bm.getName()));
|
if (value==null) continue;
|
|
try {
|
// Can't just remove the object from the parent,
|
// since in the parent, it may be wrapped in a JAXBElement
|
List<Object> theList = null;
|
if (bm.getParent() instanceof P) {
|
System.out.println("OK!");
|
theList = ((ContentAccessor)(bm.getParent())).getContent();
|
} else {
|
continue;
|
}
|
|
int rangeStart = -1;
|
int rangeEnd=-1;
|
int i = 0;
|
for (Object ox : theList) {
|
Object listEntry = XmlUtils.unwrap(ox);
|
if (listEntry.equals(bm)) {
|
if (DELETE_BOOKMARK) {
|
rangeStart=i;
|
} else {
|
rangeStart=i+1;
|
}
|
} else if (listEntry instanceof CTMarkupRange) {
|
if ( ((CTMarkupRange)listEntry).getId().equals(bm.getId())) {
|
if (DELETE_BOOKMARK) {
|
rangeEnd=i;
|
} else {
|
rangeEnd=i-1;
|
}
|
break;
|
}
|
}
|
i++;
|
}
|
|
if (rangeStart>0 && rangeEnd>rangeStart) {
|
|
// Delete the bookmark range
|
for (int j =rangeEnd; j>=rangeStart; j--) {
|
theList.remove(j);
|
}
|
|
// now add a run
|
org.docx4j.wml.R run = factory.createR();
|
org.docx4j.wml.Text t = factory.createText();
|
run.getContent().add(t);
|
t.setValue(value);
|
|
theList.add(rangeStart, run);
|
}
|
|
} catch (ClassCastException cce) {
|
log.error(cce.getMessage(), cce);
|
}
|
}
|
|
|
}
|
|
|
}
|