I went with the bookmark way, but coding with some kind of binding is probably alot smoother, though I think it's only supported in word 2007 (but don't quote me on this). Anyhow, if you do make the choice to go with bookmarks, I have some code you might find useful.
documentPart is a MainDocumentPart object that you get from WordprocessingMLPackage getMainDocumentPart. This object contains most of your document.
Traversing upwards is unpractical since many elements are wrapped in JaxbElements, thus removing information of their true parent. That's the reason why I make additional xpath queries instead of just traversing upwards. The unwrap method makes sure I don't return a JAXBElement.
Given a bookmark name, these functions provides the surrounding paragraph, cell, row, or table.
The traverse method was needed to find bookmarks in the header or footer due to the fact that only MainDocumentPart has the method getJAXBNodesViaXPath.
- Code: Select all
private Tr findBookmarkedRow(String name) throws JAXBException {
final String xpath = "//w:bookmarkStart[@w:name='" + name + "']/../../..";
List<Object> objects = documentPart.getJAXBNodesViaXPath(xpath, false);
return (org.docx4j.wml.Tr) XmlUtils.unwrap(objects.get(0));
}
private Tc findBookmarkedCell(String name) throws JAXBException {
P p = findBookmarkedParagraphInMainDocumentPart(name);
return (Tc) p.getParent();
}
private P findBookmarkedParagraphInMainDocumentPart(String name) throws JAXBException {
final String xpath = "//w:bookmarkStart[@w:name='" + name + "']/..";
List<Object> objects = documentPart.getJAXBNodesViaXPath(xpath, false);
return (org.docx4j.wml.P) XmlUtils.unwrap(objects.get(0));
}
// No xpath implementation for other parts than main document; traverse manually
private P findBookmarkedParagraphInPart(Object parent, String bookmark) {
P p = traversePartForBookmark(parent, bookmark);
return p;
}
// Used internally by findBookmarkedParagrapghInPart().
private P traversePartForBookmark(Object parent, String bookmark) {
P p = null;
List children = TraversalUtil.getChildrenImpl(parent);
if (children != null) {
for (Object o : children) {
o = XmlUtils.unwrap(o);
if (o instanceof CTBookmark) {
if (((CTBookmark) o).getName().toLowerCase().equals(bookmark)) {
return (P) parent; // If bookmark found, the surrounding P is what is interesting.
}
}
p = traversePartForBookmark(o, bookmark);
if (p != null) {
break;
}
}
}
return p;
}