// NOTICE: ORIGINAL FILE MODIFIED package com.aspose.words.examples.featurescomparison.bookmarks.deletebookmark; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.docx4j.TraversalUtil; import org.docx4j.XmlUtils; import org.docx4j.finders.RangeFinder; import org.docx4j.openpackaging.packages.WordprocessingMLPackage; import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart; import org.docx4j.wml.Body; import org.docx4j.wml.CTBookmark; import org.docx4j.wml.CTMarkupRange; import org.docx4j.wml.ContentAccessor; import com.aspose.words.examples.Utils; public class Docx4jBookmarksDeleter { protected static Logger log = LoggerFactory.getLogger(Docx4jBookmarksDeleter.class); public static void main(String[] args) throws Exception { // The path to the documents directory. String dataDir = Utils.getDataDir(Docx4jBookmarksDeleter.class); WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage .load(new java.io.File(dataDir + "Docx4j_BookmarkAdd.docx")); MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart(); // Before.. // System.out.println(XmlUtils.marshaltoString(documentPart.getJaxbElement(), true, true)); org.docx4j.wml.Document wmlDocumentEl = (org.docx4j.wml.Document) documentPart .getJaxbElement(); Body body = wmlDocumentEl.getBody(); fixRange(body.getContent(), "CTBookmark", "CTMarkupRange"); // After System.out.println(XmlUtils.marshaltoString(documentPart.getJaxbElement(), true, true)); wordMLPackage.save(new java.io.File(dataDir + "Docx4jBookmarkDeleted.docx")); System.out.println("Done."); } private static void fixRange(List<Object> paragraphs, String startElement, String endElement) throws Exception { RangeFinder rt = new RangeFinder(startElement, endElement); new TraversalUtil(paragraphs, rt); for (CTBookmark bm : rt.getStarts()) { try { // Can't just remove the object from the parent, // since in the parent, it may be wrapped in a JAXBElement List<Object> theList = null; if (bm.getParent() instanceof List) { theList = (List)bm.getParent(); // eg body.getContent() } else { theList = ((ContentAccessor)(bm.getParent())).getContent(); } Object deleteMe = null; for (Object ox : theList) { if (XmlUtils.unwrap(ox).equals(bm)) { deleteMe = ox; break; } } if (deleteMe!=null) { theList.remove(deleteMe); } } catch (ClassCastException cce) { log.error(cce.getMessage(), cce); } } for (CTMarkupRange mr : rt.getEnds()) { try { // Can't just remove the object from the parent, // since in the parent, it may be wrapped in a JAXBElement List<Object> theList = null; if (mr.getParent() instanceof List) { theList = (List)mr.getParent(); // eg body.getContent() } else { theList = ((ContentAccessor)(mr.getParent())).getContent(); } Object deleteMe = null; for (Object ox : theList) { if (XmlUtils.unwrap(ox).equals(mr)) { deleteMe = ox; break; } } if (deleteMe!=null) { theList.remove(deleteMe); } } catch (ClassCastException cce) { log.info(mr.getParent().getClass().getName()); log.error(cce.getMessage(), cce); } } // NB: this leaves begin|separate|end behind! // It would be better to delete the whole field, or just leave it, // so this is commented out. Result in Word will be "bookmark undefined!" // for (Text instrText : rt.refs) { // try { // List<Object> theList = ((ContentAccessor)(instrText.getParent())).getContent(); // Object deleteMe = null; // for (Object ox : theList) { // if (XmlUtils.unwrap(ox).equals(instrText)) { // deleteMe = ox; // break; // } // } // if (deleteMe!=null) { // theList.remove(deleteMe); // } // } catch (ClassCastException cce) { // log.info(instrText.getParent().getClass().getName()); // log.error(cce); // } // } } private static boolean remove(List<Object> theList, Object bm) { // Can't just remove the object from the parent, // since in the parent, it may be wrapped in a JAXBElement for (Object ox : theList) { if (XmlUtils.unwrap(ox).equals(bm)) { return theList.remove(ox); } } return false; } }