参考文章: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. Redis支持的数据类型

    String字符串: 格式: set key value string类型是二进制安全的.意思是redis的string可以包含任何数据.比如jpg图片或者序列化的对象 . string类型是Redi ...

  2. Dapper 一对多查询 one to many

    参考文档:Dapper one to many Table public class Person { public int Id { get; set; } public string Name { ...

  3. 洛谷 P3071 [USACO13JAN]座位Seating(线段树)

    P3071 [USACO13JAN]座位Seating 题目链接 思路: 一开始把题给读错了浪费了好多时间呜呜呜. 因为第二个撤离操作是区间修改,所以我们可以想到用线段树来做.对于第一个操作,我们只需 ...

  4. 使用django的MTV开发模式返回一个网页

    1.MTV开发模式介绍 M:Models 模型(数据) 与数据组织相关的功能.组织和存储数据的方法和模式,与数据模型相关的操作. T:Templates 模板(样式) 与表现相关的所有功能.页面展示风 ...

  5. wordpress调用文章摘要,若无摘要则自动截取文章内容字数做为摘要

    以下是调用指定分类文章列表的一个方法,作者如果有填写文章摘要则直接调用摘要:如果文章摘要忘记写了则自动截取文章内容字数做为摘要.这个方法也适用于调用description标签 <ul> & ...

  6. LeetCode 325. Maximum Size Subarray Sum Equals k

    原题链接在这里:https://leetcode.com/problems/maximum-size-subarray-sum-equals-k/ 题目: Given an array nums an ...

  7. 通过日志解决问题的一个小例子-http换端口

    这个例子是将http服务的监听端口改为8999后重启服务报错: 此时查看日志/var/log/message,显示如下: 如红笔所示轨迹得到设置端口类型的命令:semanage port -a -t ...

  8. 腾讯蓝鲸cmdb源码编译

    腾讯蓝鲸 cmdb 源码编译环境依赖 环境包参考: golang >= 1.8 python >= nodejs >= (编译过程中需要可以连公网下载依赖包) Python 环境 w ...

  9. Xml解析作业与Xml建模andXml建模作业

    作业:config.xml解析 1.获取所有action中的type的值 public static void main(String[] args) throws Exception { Input ...

  10. 【数论】[涨姿势:同余]P2312解方程

    题目描述 已知多项式方程:\(a_0 + a_1x + a_2x^2+...+a_nx^n = 0\) 求这个方程在[1,m]内的整数解 \(1\leq n\leq100,|a_i|\leq 10^{ ...