javaapache-poi

How to generate a link inside a footnote with Apache POI?


I am able to create footnotes, and I'm able to make links, but when I try to make a link inside a footnote Word refuses to open the resulting document.

Here's a minimal example that reproduces the problem:

import java.io.File;
import java.io.FileOutputStream;

import org.apache.poi.xwpf.usermodel.XWPFAbstractFootnoteEndnote;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHyperlinkRun;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRelation;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHyperlink;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;

public class Test {
  public static void main(String[] argv) throws Exception {
    XWPFDocument document = new XWPFDocument();
    XWPFParagraph para = document.createParagraph();

    XWPFRun tmpRun = para.createRun();
    tmpRun.setText("LALALALAALALAAAA");

    XWPFAbstractFootnoteEndnote note = para.getDocument().createFootnote();

    XWPFParagraph ipara = note.createParagraph();
    XWPFRun irun = ipara.createRun();
    irun.setText("In the footnote");

    String href = "https://www.garshol.priv.no";
    CTHyperlink hyperlink = ipara.getCTP().addNewHyperlink();
    String rId = ipara.getDocument().getPackagePart().addExternalRelationship(href, XWPFRelation.HYPERLINK.getRelation()).getId();
    hyperlink.setId(rId);

    XWPFHyperlinkRun hyperlinkRun = new XWPFHyperlinkRun(
      hyperlink, CTR.Factory.newInstance(), ipara);
    CTR run = hyperlink.addNewR();
    run.addNewT().setStringValue("And here is a link");

    ipara.addRun(hyperlinkRun);

    para.addFootnoteReference(note);

    document.write(new FileOutputStream(new File("fuck.docx")));
    document.close();
  }
}

We've figured out that the problem is that this file is missing inside the .docx: word/_rels/footnotes.xml.rels. It should contain this XML:

<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
  <Relationship Id="rId3"
    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
    Target="https://www.garshol.priv.no"
    TargetMode="External"/>
</Relationships>

If I add that, Word will open the document.

The big question is ... why doesn't Apache POI add this file? What can I do to make it add the file with the correct content? (I've tried Apache POI 5.2.5 and 5.5.1, same result.)


Solution

  • The problem is that you're adding the hyperlink relationship to the wrong package part. When you call:

    ipara.getDocument().getPackagePart().addExternalRelationship(...)
    

    This adds the relationship to word/_rels/document.xml.rels (the main document's relationships), but footnotes live in a separate part (word/footnotes.xml) and need their relationships in word/_rels/footnotes.xml.rels.

    You need to add the relationship to the footnotes package part, not the document's package part

    so instead of

    String rId = ipara.getDocument().getPackagePart().addExternalRelationship(href, XWPFRelation.HYPERLINK.getRelation()).getId();
    

    yo need

    String rId = document.getFootnotes().getPackagePart().addExternalRelationship(href, XWPFRelation.HYPERLINK.getRelation()).getId();