Search code examples
javaxmldocx4j

Docx4j replace a text by picture in XML


I want replace a text by a picture in the XML structure of a docx file. I've tried something like that: First I search the good text in the XML and after I create a drawing object to put the picture in.

List<Object> list = this.getDocumentPart().getJAXBNodesViaXPath(xpath, false);
org.docx4j.wml.ObjectFactory  factory  =  Context.getWmlObjectFactory();
org.docx4j.wml.P para = factory.createP();
org.docx4j.wml.Drawing draw = factory.createDrawing();
((R)list.get(0)).getContent().clear();
((R)list.get(0)).getContent().add(draw);
para.getContent().add(((R)list.get(0)));
try {
    this.getWordMLPackage().save(new java.io.File("C:\\user\\result.docx") );
} catch (Docx4JException e) {
    e.printStackTrace();
}

Now I don't know what put in the draw to add my picture, and at this step when I want to open my docx there is a problem. Any idea ?


Solution

  • I fix the problem so I post the solution, maybe it will help someone.

    First you need to know that we are going to add a Inline in the Drawing so we need 2 funtion. The first to convert the picture in a ByteArray;

    private static byte[] convertImageToByteArray(File file) throws FileNotFoundException, IOException {
        InputStream is = new FileInputStream(file );
        long length = file.length();
        if (length > Integer.MAX_VALUE) {
            System.out.println("Fichier trop volumineux.");
        }
        byte[] bytes = new byte[(int)length];
        int offset = 0;
        int numRead = 0;
        while (offset < bytes.length  && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
            offset += numRead;
        }
        if (offset < bytes.length) {
            System.out.println("Impossible de lire en entier le fichier: " + file.getName());
        }
        is.close();
        return bytes;
    }
    

    After that you need to create the Inline:

    public Inline createInline(File filePict) throws Exception{
        byte[] bytes = convertImageToByteArray(filePict);
        BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(this.getWordMLPackage(), bytes);
        int id1 = 1;
        int id2 = 2;
        Inline inline = imagePart.createImageInline("Filename hint", filePict.getName(), id1, id2, false);
        return inline;
    }
    

    And at the add the Inline to the Drawing:

    File fileLogo = new File(this.cusDir+mappings.get("logo"));
    org.docx4j.wml.Drawing draw = factory.createDrawing();
    ((R)list.get(i)).getContent().clear();
    ((R)list.get(i)).getContent().add(draw);
    draw.getAnchorOrInline().add(createInline(fileLogo));