Reputation: 1249
I am using Docx4J to modify docx templates and put values in place of placeholders in the template that are predefined.
so far, i had been successful in finding and replacing paragraphs and texts, tables, images etc. But i am not yet successful in finding Header and/or Footer elements of the document.
I am using
WordprocessingMLPackage wordMLPackage =
WordprocessingMLPackage.load(new java.io.File(inputfilepath));
wordMLPackage.getMainDocumentPart();
to search for elements in the template.
Upvotes: 5
Views: 10099
Reputation: 564
This is how I managed to replace keyholders on the footer(In Java, no XML). The piece that I was missing is the :
JaxbXmlPart part = (JaxbXmlPart) relationshipPart.getPart(r);
from the source-code MailMerger.java that JasonPlutext mentioned, stated in the line 410. So thank you JasonPlutext!
public static void replaceElementFromFooter(WordprocessingMLPackage template, String nameplace, String placeholder, String newValue) throws Docx4JException {
List<Object> result = new ArrayList<Object>();
RelationshipsPart relationshipPart = template.getMainDocumentPart().getRelationshipsPart();
List<Relationship> relationships = relationshipPart.getRelationships().getRelationship()
for (Relationship r : relationships) {
if (r.getType().equals(nameplace)) {
JaxbXmlPart part = (JaxbXmlPart) relationshipPart.getPart(r);
List<Object> texts = getAllElementsFromObject(part.getContents(), Text.class);
replaceTextElement(texts, placeholder, newValue);
}
}
return result;
}
private static List<Object> getAllElementsFromObject(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;
}
private static void replaceTextElement(List<Object> texts, String placeholder, String newValue) {
for (Object element : texts) {
Text textElement = (Text) element;
if (textElement.getValue().contains(placeholder)) {
String replacedValue = textElement.getValue().replaceAll(placeholder, newValue);
textElement.setValue(replacedValue);
}
}
}
Upvotes: 3
Reputation: 227
If you search and replace in the XML you can use:
String xpath = "//w:r[w:t[contains(text(), 'placeholder')]]";
List<Object> list = wordMLPackage.getHeaderFooterPolicy().getDefaultHeader().getJAXBNodesViaXPath(xpath, false);
list.addAll(wordMLPackage.getHeaderFooterPolicy().getDefaultFooter().getJAXBNodesViaXPath(xpath, false));
The list contains all the nodes where the placeholder is present. After you can get the type of the placeholder (text, picture ...) with the method I explain here (it's for text but easy to adapt): replace_placeholder
Upvotes: 0
Reputation: 15878
For your application, you can mimic the code in https://github.com/plutext/docx4j/blob/master/src/main/java/org/docx4j/model/datastorage/BindingHandler.java at line 145
A similar approach is taken in https://github.com/plutext/docx4j/blob/master/src/main/java/org/docx4j/model/fields/merge/MailMerger.java at line 124
Upvotes: 5