问题
I'm using docx4j in an XPages application to create Word documents containing content from an XPage. The Word document (in .docx format) is created based on a template (in .dotx format). One bookmark from my .dotx template is as follows:
<w:p>
<w:bookmarkStart w:name="Fachkompetenz" w:id="0"/>
<w:bookmarkEnd w:id="0"/>
</w:p>
Using the function
private static List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {
List<Object> result = new ArrayList<Object>();
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;
}
I can get the p object by calling
List<Object> texts = getAllElementFromObject(template.getMainDocumentPart(), P.class);
or the CTBookmark object calling
List<Object> texts = getAllElementFromObject(template.getMainDocumentPart(), P.class);
However, once I have these objects I don't know how to add text (XPage content) to replace the bookmark. I've read as much as I can find on the internet on this topic but can't find any way of doing this. Does anybody have any suggestion?
回答1:
If you can, you might want to reconsider your approach.
Since bookmarks are "point" tags, it is not so easy to replace their content. For example, the opening tag could be in a top level paragraph, and the closing one in a table cell!
You may find content control data binding works better.
That said, assuming your bookmark start and end is in a single p (as per your example xml), you could try the following approach:
- find the bookmark start element
- use getParent to access the list containing it
- iterate through the list to find the end element
- replace the content between the 2 list entries
At step 4, you'll be wanting to insert new run (w:r) objects containing text (w:t). You can upload a sample docx to the docx4j webapp to generate code for that.
BookmarksReplaceWithText.java may help.
回答2:
I managed to solve this problem by using the below function. It may need refactoring in future but it works for now:
private void replaceParagraph(String placeholder, String textToAdd, WordprocessingMLPackage template) {
List<Object> paragraphs = getAllElementFromObject(template.getMainDocumentPart(), P.class);
for (Object p : paragraphs) {
RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
new TraversalUtil(p, rt);
for (CTBookmark content : rt.getStarts()) {
if (content.getName().equals(placeholder)) {
List<Object> theList = null;
if (content.getParent() instanceof P) {
theList = ((ContentAccessor)(content.getParent())).getContent();
} else {
continue;
}
if (textToAdd == ""){
int index = theList.indexOf(content);
Object removed = theList.remove(index);
} else {
org.docx4j.wml.R run = factory.createR();
org.docx4j.wml.Text t2 = factory.createText();
run.getContent().add(t2);
t2.setValue(textToAdd);
theList.add(0, run);
break;
}
}
}
}
}
Jason, thanks for your help.
来源:https://stackoverflow.com/questions/24998463/xpages-docx4j-replacing-a-bookmark-with-text