I am using Word to create templates that contain many variables. I will read and parse the Word document to set bookmarks for the variables. Each variable is a XWPFRun object. How can I set a bookmark for a XWPFRun object? Below is the response from chatgpt, but CTR doesn't have addNewBookmarkStart and addNewBookmarkEnd.
for (XWPFParagraph paragraph : document.getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
// Check if the run meets your criteria
if (/* condition */) {
// Create a bookmark for the run
run.getCTR().addNewBookmarkStart().setName("bookmark_name");
run.getCTR().addNewBookmarkEnd();
}
}
}
In java poi XWPF word - create bookmark in new document I have shown how to create bookmarks in a new XWPFDocument.
If you look at the document.xml created, you will find:
<w:p>
...
<w:bookmarkStart w:name="testing_string" w:id="1"/>
<w:r>
<w:t xml:space="preserve">testing string </w:t>
</w:r>
<w:bookmarkEnd w:id="1"/>
...
</w:p>
The bookmarkStart
is immediately before the text run and the bookmarkEnd
is immediately after the text run in paragraph. All elements are children of the paragraph elements on same level.
If the need is to bookmark already existent XWPFRun
s, then one need to insert the bookmarkStart
immediately before and bookmarkEnd
immediately after the XWPFRun
in XWPFParagraph
. This only is possible using a XmlCursor
.
Example:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark;
import org.apache.xmlbeans.XmlCursor;
import java.math.BigInteger;
public class WordBookmarkXWPFRun {
static void bookmarkXWPFRun(XWPFRun run, String name, int id) {
// insert bookmarkStart immediately before the run
XmlCursor cursor = run.getCTR().newCursor();
String uri = CTBookmark.type.getName().getNamespaceURI();
String localPart = "bookmarkStart";
cursor.beginElement(localPart, uri);
cursor.toParent();
CTBookmark bookmarkStart = (CTBookmark)cursor.getObject();
bookmarkStart.setName(name);
bookmarkStart.setId(BigInteger.valueOf(id));
// insert bookmarkEnd immediately after the run
cursor = run.getCTR().newCursor();
if (!cursor.toNextSibling()) { // is there a next sibling?
// if not, go to end of parent element to insert bookmarkEnd there
cursor.toParent();
cursor.toEndToken();
}
localPart = "bookmarkEnd";
cursor.beginElement(localPart, uri);
cursor.insertAttributeWithValue("id", uri, String.valueOf(id));
}
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument(new FileInputStream("./WordDocument.docx"));
int id = 1;
for (XWPFParagraph paragraph : document.getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
// Check if the run meets your criteria
if (/* condition */ true ) { // this will bookmark every single tect run in document
// Create a bookmark for the run
bookmarkXWPFRun(run, "bookmark_name_" + id, id++);
}
}
}
FileOutputStream out = new FileOutputStream("./WordDocumentBookmarked.docx");
document.write(out);
out.close();
document.close();
}
}