解决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 }