feiyu02
2024-08-13 b8cc591541b88dd2bb93f111f8e8075842dce7ca
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package cn.flightfeather.supervision.docx4j.simpleDemo;
 
import org.docx4j.TraversalUtil;
import org.docx4j.XmlUtils;
import org.docx4j.finders.RangeFinder;
import org.docx4j.jaxb.Context;
import org.docx4j.model.fields.merge.DataFieldName;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
 
/**
 * Replace text between w:bookmarkStarts and corresponding w:bookmarkEnds
 * with specified data, matching on bookmark's @w:name 
 *
 */
public class BookmarksReplaceWithText {
    
    /*
     * Requirements:
     * - bookmarkStart and End must be in the same paragraph
     * - no attempt is made to check whether the start of some other bookmark is
     *   in that range.  If it is, it will get deleted!
     * - no attempt is made to preserve the rPr
     * - mdp only right now
     */
    
    protected static Logger log = LoggerFactory.getLogger(BookmarksReplaceWithText.class);
    
    private static boolean DELETE_BOOKMARK = false;
    
    private static org.docx4j.wml.ObjectFactory factory = Context.getWmlObjectFactory();
    
 
    public static void main(String[] args) throws Exception {
        
        Map<DataFieldName, String> map = new HashMap<DataFieldName, String>();
        map.put( new DataFieldName("bm1"), "whale shark");
        
 
        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage
                .load(new java.io.File(System.getProperty("user.dir")
                        + "/bm1.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();
        
        BookmarksReplaceWithText bti = new BookmarksReplaceWithText();
 
        bti.replaceBookmarkContents(body.getContent(), map);
        
        // After
        // System.out.println(XmlUtils.marshaltoString(documentPart.getJaxbElement(), true, true));
        
        // save the docx...
        wordMLPackage.save(new java.io.File(System.getProperty("user.dir") + "/OUT_BookmarksTextInserter.docx"));
    }
 
    private  void replaceBookmarkContents(List<Object> paragraphs,  Map<DataFieldName, String> data) throws Exception {
 
        RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
        new TraversalUtil(paragraphs, rt);
        
        for (CTBookmark bm : rt.getStarts()) {
            
            // do we have data for this one?
            if (bm.getName()==null) continue;
            String value = data.get(new DataFieldName(bm.getName()));
            if (value==null) continue;
                
            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 P) {
                    System.out.println("OK!");
                    theList = ((ContentAccessor)(bm.getParent())).getContent();
                } else {
                    continue;
                }
 
                int rangeStart = -1;
                int rangeEnd=-1;
                int i = 0;
                for (Object ox : theList) {
                    Object listEntry = XmlUtils.unwrap(ox); 
                    if (listEntry.equals(bm)) {
                        if (DELETE_BOOKMARK) {
                            rangeStart=i;
                        } else {
                            rangeStart=i+1;                            
                        }
                    } else if (listEntry instanceof  CTMarkupRange) {
                        if ( ((CTMarkupRange)listEntry).getId().equals(bm.getId())) {
                            if (DELETE_BOOKMARK) {
                                rangeEnd=i;
                            } else {
                                rangeEnd=i-1;                            
                            }
                            break;
                        }
                    }
                    i++;
                }
                
                if (rangeStart>0 && rangeEnd>rangeStart) {
                    
                    // Delete the bookmark range
                    for (int j =rangeEnd; j>=rangeStart; j--) {
                        theList.remove(j);
                    }
                    
                    // now add a run
                    org.docx4j.wml.R  run = factory.createR();
                    org.docx4j.wml.Text  t = factory.createText();
                    run.getContent().add(t);        
                    t.setValue(value);
                    
                    theList.add(rangeStart, run);
                }
                
            } catch (ClassCastException cce) {
                log.error(cce.getMessage(), cce);
            }
        }
 
        
    }
 
    
}