Search code examples
javaxpagesdocx4j

XPages - docx4j - replacing a bookmark with text


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?


Solution

  • 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.