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

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

 package com.tool;

 import java.util.regex.Pattern;

 import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException; import org.docx4j.XmlUtils;
import org.docx4j.jaxb.Context;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.Document; public class DocxVariableClearUtils { /**
* 清理文档接口方法,将被格式 分割的 替换变量 还原
*
* @param documentPart
*/
public static boolean cleanDocumentPart(MainDocumentPart documentPart) throws Exception {
if (documentPart == null) {
return false;
}
Document document = documentPart.getContents();
String wmlTemplate = XmlUtils.marshaltoString(document, true, false, Context.jc);
document = (Document) XmlUtils.unwrap(DocxVariableClearUtils.doCleanDocumentPart(wmlTemplate, Context.jc));
documentPart.setContents(document);
return true;
} /**
* 去任意XML标签 及 空白字符
*/
private static final Pattern XML_PATTERN = Pattern.compile("<[^>]*>|\\s"); private DocxVariableClearUtils() {
} /**
* start符号
*/
private static final char PREFIX = '$'; /**
* 中包含
*/
private static final char LEFT_BRACE = '{'; /**
* 结尾
*/
private static final char RIGHT_BRACE = '}'; /**
* 未开始
*/
private static final int NONE_START = -1; /**
* 未开始
*/
private static final int NONE_START_INDEX = -1; /**
* 开始
*/
private static final int PREFIX_STATUS = 1; /**
* 左括号
*/
private static final int LEFT_BRACE_STATUS = 2; /**
* 右括号
*/
private static final int RIGHT_BRACE_STATUS = 3; /**
* doCleanDocumentPart
*
* @param wmlTemplate
* @param jc
* @return
* @throws JAXBException
*/
public static Object doCleanDocumentPart(String wmlTemplate, JAXBContext jc) throws JAXBException {
System.out.println("======执行清除方法=====");
// 进入变量块位置
int curStatus = NONE_START;
// 开始位置
int keyStartIndex = NONE_START_INDEX;
// 当前位置
int curIndex = 0;
char[] textCharacters = wmlTemplate.toCharArray();
StringBuilder documentBuilder = new StringBuilder(textCharacters.length);
documentBuilder.append(textCharacters);
// 新文档
StringBuilder newDocumentBuilder = new StringBuilder(textCharacters.length);
// 最后一次写位置
int lastWriteIndex = 0;
for (char c : textCharacters) {
switch (c) {
case PREFIX:
// TODO 不管其何状态直接修改指针,这也意味着变量名称里面不能有PREFIX
keyStartIndex = curIndex;
curStatus = PREFIX_STATUS;
break;
case LEFT_BRACE:
if (curStatus == PREFIX_STATUS) {
curStatus = LEFT_BRACE_STATUS;
}
break;
case RIGHT_BRACE:
if (curStatus == LEFT_BRACE_STATUS) {
// 接上之前的字符
newDocumentBuilder.append(documentBuilder.substring(lastWriteIndex, keyStartIndex));
// 结束位置
int keyEndIndex = curIndex + 1;
// 替换
String rawKey = documentBuilder.substring(keyStartIndex, keyEndIndex);
System.out.println("-----需要替换的标签:"+rawKey);
// 干掉多余标签
String mappingKey = XML_PATTERN.matcher(rawKey).replaceAll("");
System.out.println("-----替换完成的字符:"+mappingKey); // if (!mappingKey.equals(rawKey)) {
// char[] rawKeyChars = rawKey.toCharArray();
// // 保留原格式
// StringBuilder rawStringBuilder = new StringBuilder(rawKey.length());
// // 去掉变量引用字符
// for (char rawChar : rawKeyChars) {
// if (rawChar == PREFIX || rawChar == LEFT_BRACE || rawChar == RIGHT_BRACE) {
// continue;
// }
// rawStringBuilder.append(rawChar);
// }
// // FIXME 要求变量连在一起
// String variable = mappingKey.substring(2, mappingKey.length() - 1);
// System.out.println("-----替换完成的变量variable:"+variable);
// System.out.println("-----rawStringBuilder:"+rawStringBuilder);
// int variableStart = rawStringBuilder.indexOf(variable);
// if (variableStart > 0) {
// rawStringBuilder = rawStringBuilder.replace(variableStart, variableStart + variable.length(), mappingKey);
// System.out.println("-----最后rawStringBuilder:"+rawStringBuilder);
// }
// newDocumentBuilder.append(rawStringBuilder.toString());
// } else {
newDocumentBuilder.append(mappingKey);
// }
lastWriteIndex = keyEndIndex; curStatus = NONE_START;
keyStartIndex = NONE_START_INDEX;
}
default:
break;
}
curIndex++;
}
// 余部
if (lastWriteIndex < documentBuilder.length()) {
newDocumentBuilder.append(documentBuilder.substring(lastWriteIndex));
}
return XmlUtils.unmarshalString(newDocumentBuilder.toString(), jc);
}
}

解决docx4j 变量替换 由于变量存在样式式或空白字符 导致替换失败问题的更多相关文章

  1. 解决mybatis-plus更新数据的时候,有值为空导致更新失败的问题

    问题 在用mybatis-plus更新数据的时候,更新失败,错误信息如下: Cause: org.apache.ibatis.type.TypeException: Could not set par ...

  2. 彻底解决Eclipse自动补全变量名及变量名后面追加类型名

    彻底解决Eclipse自动补全变量名问题的方法步骤 发布于 2014-11-04 14:53   已被阅读 31613159 次 大家使用eclipse或者MyEclipse敲代码的时候,是不是都被这 ...

  3. SQL*Plus中替换变量与定义变量

    替换变量 SQL*Plus中的替换变量又叫替代变量,它一般用来临时存储相关数据:在SQL语句之间传递值.一般使用&或&&前缀来指定替换变量. 关于使用替换变量,一般是利用其创建 ...

  4. Shell命令替换与变量替换

    命令替换 命令替换是指Shell可以先执行命令,将输出结果暂时保存,在适当的地方输出.命令替换的语法: `command` 注意是反引号,不是单引号,这个键位于 Esc 键下方.下面的例子中,将命令执 ...

  5. Linux编程 21 shell编程(环境变量,用户变量,命令替换)

    一.概述 这篇介绍shell的变量使用,跟其实语言一样,都有声明变量,使用变量,在shell中变量允许你临时地将信息存储中shell脚本中,以便和脚本的其他命令一起使用. 1.1 环境变量 在前面章节 ...

  6. Java基础-final变量和普通变量的区别

    当用final作用于类的成员变量时,成员变量(注意是类的成员变量,局部变量只需要保证在使用之前被初始化赋值即可)必须在定义时或者构造器中进行初始化赋值,而且final变量一旦被初始化赋值之后,就不能再 ...

  7. 浅析c语言中的变量(局部变量,外部变量,静态变量,寄存器变量)[转]

    c语言中变量分为四类,分别是 1.auto   自动变量 2.static   静态存贮分配变量(又分为内部静态和外部静态) 3.extern  全程变量(用于外部变量说明) 4.register   ...

  8. java 获取系统变量(环境变量和设置变量)

    前言 环境变量这个概念不陌生, 就是操作系统的环境变量. 系统变量就是java本身维护的变量. 通过 System.getProperty 的方式获取. 对于不同的操作系统来说, 环境变量的处理可能会 ...

  9. java 获取系统变量(环境变量和环境变量)

    前言 环境变量这个概念不陌生, 就是操作系统的环境变量. 系统变量就是java本身维护的变量. 通过 System.getProperty 的方式获取. 对于不同的操作系统来说. 环境变量的处理可能会 ...

随机推荐

  1. MySQL倒序索引测试2

    测试环境 MySQL Community Server 8.0.17 准备测试数据 DROP TABLE TB001; CREATE TABLE TB001(ID INT PRIMARY KEY AU ...

  2. 手写神经网络Python深度学习

    import numpy import scipy.special import matplotlib.pyplot as plt import scipy.misc import glob impo ...

  3. C++学习(7)—— 函数提高

    1. 函数默认参数 在C++中,函数的形参列表中的形参是可以有默认值的 语法:返回值类型 函数名 (参数=默认值){} 注意 如果某个位置已经有了默认参数,那么从这个位置往后,从左到右都必须有默认值 ...

  4. iscroll.js的简单使用方法

    参考链接:https://www.cnblogs.com/Renyi-Fan/tag/js%E6%8F%92%E4%BB%B6/default.html?page=2 目录 一.总结 一句话总结:Sc ...

  5. 利用form.submit提交表单导出文件到客户端浏览器, 提示下载!

    本来是想利用ajax提交json数据到服务端, 让服务端生成一个excel文件并提示客户端浏览器下载的. 但是搞了很久发现ajax方式是无法触发浏览器弹出文件下载的. 网上很多的方案都是说利用form ...

  6. selenium-1-python

    python selenium from selenium import webdriver from selenium.webdriver.common.action_chains import A ...

  7. C语言入门hello world

    1.安装软件 c语言开发工具众多,初学者推荐使用Dev-Cpp 5.6.3 TDM-GCC x64 4.8.1 Setup.exe:安装过程全部默认安装即可. 2.使用Dev-Cpp编写第一个入门实例 ...

  8. 2019牛客暑期多校训练营(第九场)B:Quadratic equation (二次剩余求mod意义下二元一次方程)

    题意:给定p=1e9+7,A,B.  求一对X,Y,满足(X+Y)%P=A; 且(X*Y)%P=B: 思路:即,X^2-BX+CΞ0;  那么X=[B+-sqrt(B^2-4C)]/2: 全部部分都要 ...

  9. python基础语法1 用户交互,基本数据类型,格式化输出,运算符

    与用户交互: 输入: python2: input一定要声明你输入的类型 >>> input(">>:") >>:sean Traceba ...

  10. Servlet 容器

    Servlet容器主要是JavaWeb应用提供运行时环境,所以也可以称之为JavaWeb应用容器,或者Servlet/JSP容器.Servlet容器主要负责管理Servlet.JSP的生命周期以及它们 ...