解决docx4j 变量替换 由于变量存在样式式或空白字符 导致替换失败问题

参考文章:https://blog.csdn.net/qq_35598240/article/details/84439929

使用docx4j进行变量替换时 变量(形如:${变量})必须是无格式的,并且不能有拼写检查等,官方提供了一个VariablePrepare.prepare(wordMLPackage)的方法,但是只能解决拼写检查等少数情况,对样式(如加粗)等无效,从网上找到一篇博文(见参考文章),方法可行,但保留格式部分不能正常运行,注释后使用.代码如下:

  1 package com.tool;
  2 
  3 import java.util.regex.Pattern;
  4 
  5 import javax.xml.bind.JAXBContext;
  6 import javax.xml.bind.JAXBException;
  7 
  8 import org.docx4j.XmlUtils;
  9 import org.docx4j.jaxb.Context;
 10 import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
 11 import org.docx4j.wml.Document;
 12 
 13 public class DocxVariableClearUtils {
 14 
 15     /**
 16      * 清理文档接口方法,将被格式 分割的 替换变量 还原
 17      *
 18      * @param documentPart
 19      */
 20     public static boolean cleanDocumentPart(MainDocumentPart documentPart) throws Exception {
 21         if (documentPart == null) {
 22             return false;
 23         }
 24         Document document = documentPart.getContents();
 25         String wmlTemplate = XmlUtils.marshaltoString(document, true, false, Context.jc);
 26         document = (Document) XmlUtils.unwrap(DocxVariableClearUtils.doCleanDocumentPart(wmlTemplate, Context.jc));
 27         documentPart.setContents(document);
 28         return true;
 29     }
 30 
 31     /**
 32      * 去任意XML标签 及 空白字符
 33      */
 34     private static final Pattern XML_PATTERN = Pattern.compile("<[^>]*>|\\s");
 35 
 36     private DocxVariableClearUtils() {
 37     }
 38 
 39     /**
 40      * start符号
 41      */
 42     private static final char PREFIX = '$';
 43 
 44     /**
 45      * 中包含
 46      */
 47     private static final char LEFT_BRACE = '{';
 48 
 49     /**
 50      * 结尾
 51      */
 52     private static final char RIGHT_BRACE = '}';
 53 
 54     /**
 55      * 未开始
 56      */
 57     private static final int NONE_START = -1;
 58 
 59     /**
 60      * 未开始
 61      */
 62     private static final int NONE_START_INDEX = -1;
 63 
 64     /**
 65      * 开始
 66      */
 67     private static final int PREFIX_STATUS = 1;
 68 
 69     /**
 70      * 左括号
 71      */
 72     private static final int LEFT_BRACE_STATUS = 2;
 73 
 74     /**
 75      * 右括号
 76      */
 77     private static final int RIGHT_BRACE_STATUS = 3;
 78 
 79 
 80     /**
 81      * doCleanDocumentPart
 82      *
 83      * @param wmlTemplate
 84      * @param jc
 85      * @return
 86      * @throws JAXBException
 87      */
 88     public static Object doCleanDocumentPart(String wmlTemplate, JAXBContext jc) throws JAXBException {
 89         System.out.println("======执行清除方法=====");
 90         // 进入变量块位置
 91         int curStatus = NONE_START;
 92         // 开始位置
 93         int keyStartIndex = NONE_START_INDEX;
 94         // 当前位置
 95         int curIndex = 0;
 96         char[] textCharacters = wmlTemplate.toCharArray();
 97         StringBuilder documentBuilder = new StringBuilder(textCharacters.length);
 98         documentBuilder.append(textCharacters);
 99         // 新文档
100         StringBuilder newDocumentBuilder = new StringBuilder(textCharacters.length);
101         // 最后一次写位置
102         int lastWriteIndex = 0;
103         for (char c : textCharacters) {
104             switch (c) {
105                 case PREFIX:
106                     // TODO 不管其何状态直接修改指针,这也意味着变量名称里面不能有PREFIX
107                     keyStartIndex = curIndex;
108                     curStatus = PREFIX_STATUS;
109                     break;
110                 case LEFT_BRACE:
111                     if (curStatus == PREFIX_STATUS) {
112                         curStatus = LEFT_BRACE_STATUS;
113                     }
114                     break;
115                 case RIGHT_BRACE:
116                     if (curStatus == LEFT_BRACE_STATUS) {
117                         // 接上之前的字符
118                         newDocumentBuilder.append(documentBuilder.substring(lastWriteIndex, keyStartIndex));
119                         // 结束位置
120                         int keyEndIndex = curIndex + 1;
121                         // 替换
122                         String rawKey = documentBuilder.substring(keyStartIndex, keyEndIndex);
123                         System.out.println("-----需要替换的标签:"+rawKey);
124                         // 干掉多余标签
125                         String mappingKey = XML_PATTERN.matcher(rawKey).replaceAll("");
126                         System.out.println("-----替换完成的字符:"+mappingKey);
127                         
128 //                        if (!mappingKey.equals(rawKey)) {
129 //                            char[] rawKeyChars = rawKey.toCharArray();
130 //                            // 保留原格式
131 //                            StringBuilder rawStringBuilder = new StringBuilder(rawKey.length());
132 //                            // 去掉变量引用字符
133 //                            for (char rawChar : rawKeyChars) {
134 //                                if (rawChar == PREFIX || rawChar == LEFT_BRACE || rawChar == RIGHT_BRACE) {
135 //                                    continue;
136 //                                }
137 //                                rawStringBuilder.append(rawChar);
138 //                            }
139 //                            // FIXME 要求变量连在一起
140 //                            String variable = mappingKey.substring(2, mappingKey.length() - 1);
141 //                            System.out.println("-----替换完成的变量variable:"+variable);
142 //                            System.out.println("-----rawStringBuilder:"+rawStringBuilder);
143 //                            int variableStart = rawStringBuilder.indexOf(variable);
144 //                            if (variableStart > 0) {
145 //                                rawStringBuilder = rawStringBuilder.replace(variableStart, variableStart + variable.length(), mappingKey);
146 //                                System.out.println("-----最后rawStringBuilder:"+rawStringBuilder);
147 //                            }
148 //                            newDocumentBuilder.append(rawStringBuilder.toString());
149 //                        } else {
150                             newDocumentBuilder.append(mappingKey);
151 //                        }
152                         lastWriteIndex = keyEndIndex;
153 
154                         curStatus = NONE_START;
155                         keyStartIndex = NONE_START_INDEX;
156                     }
157                 default:
158                     break;
159             }
160             curIndex++;
161         }
162         // 余部
163         if (lastWriteIndex < documentBuilder.length()) {
164             newDocumentBuilder.append(documentBuilder.substring(lastWriteIndex));
165         }
166         return XmlUtils.unmarshalString(newDocumentBuilder.toString(), jc);
167     }
168 }

 

posted @ 2019-11-28 14:33  dirgo  阅读(741)  评论(0编辑  收藏  举报