参考文章: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. java操作excel-----poi

    一.所需依赖包 1.使用maven会自动导入相关依赖,所以只需要导入2007版的的包,其他包自动导入,包括2003所需jar包. <dependency> <groupId>o ...

  2. 学习Spring5源码时所遇到的坑

    学习Spring5源码时所遇到的坑 0)本人下载的源码版本是 spring-framework-5.0.2.RELEASE 配置好gradle环境变量之后,cmd进入到spring项目,执行gradl ...

  3. PHP二维数组用某个字段的值当做键名

    $array = array( array(','name'=>'tom'), array(','name'=>'jerry'), array(','name'=>'spike') ...

  4. 【原】命令行增删改查阿里云 DNS

    命令行解析阿里云 DNS 项目地址:https://github.com/liyongjian5179/alidns 首先需要获取阿里云账号账号的AccessKeyID及AccessKeySecret ...

  5. HttpRunner V2.x 学习(一)

    官方说明文档: https://cn.httprunner.org/ 作者(李隆)博客: https://debugtalk.com/ 1.介绍 HttpRunner 是一款面向 HTTP(S) 协议 ...

  6. 算法dfs——二叉搜索树中最接近的值 II

    901. 二叉搜索树中最接近的值 II 中文 English 给定一棵非空二叉搜索树以及一个target值,找到 BST 中最接近给定值的 k 个数. 样例 样例 1: 输入: {1} 0.00000 ...

  7. php装饰器模式(decorator pattern)

    十一点了. <?php /* The decorator pattern allows behavior to be added to an individual object instance ...

  8. php的类使用样例

    这个demo.差不多php的类的主要知识点都用到了. public,private关键字, namespace,use命令空间, require导入, interface复用, abstract抽象类 ...

  9. selenium入门知识

    自动化测试 重复测试.性能测试.压力测试 快速.可靠.可重复.可程序化.广泛的 自动化测试适合场合 回归测试.更多更频繁的测试.手工测试无法实现的工作.跨平台产品的测试.重复性很强的操作 不适合场合 ...

  10. ModelMetadataProviders 获取类型元数据

    var aa = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(LogModel)).Properties;