最近弄一个项目,需要读取xml文件里面的内容生成word文档,网上找了很多方案,最后选择用freemarker来处理,一是读写起来比较简单,而是不需要设置复杂的Word格式且一旦格式有变化重新生成模板就成,不需要改java代码。这篇文档有介绍怎么生成xml模板以及静态的例子,我也是参考这篇来处理的。链接:
http://blog.csdn.net/lun379292733/article/details/18673081
我这里写个简单的过程吧,加深下印象。
一、创建模板文件:
1、找到需要做成模板的word文档,将其中的关键数据用EL表达式来替换,譬如:
姓名:wjl
改成:
姓名:${name}
2、将替换成EL之后的word另存为xml(注意保存时选择“只保存数据”);
3、修改xml文件的后缀名,改成ftl格式。
4、我的word模板里面有个需要循环的列表,列表里面的内容我定义成了${content},但是这个内容有很多,类似于循环一样,因此需要添加<#list>来体现循环,如图:
其中,真正的标签是<#list>,fileList是要循环的list,file是别面,用<c:foreach>来说就是:fileList是放在item里面的东西,file类似于var里面的东西。
5、我的这个ftl文件名称为:word.ftl,放在config文件夹下(不是包,参考的那篇文章是放在包下的,我这个放在文件夹下)。
二、读取xml文件生成word:1、createWordFile用来组装业务,包括读取xml数据生成word,并返回给调用出的结果。
/**
* 该方法用来生成word文件
* @param:父级文件夹名称
* @param:需要处理的文件所在目录
* */
public boolean createWordFile(String parentFileName,String newFilePath) throws Exception{
boolean result=false;
File xmlFile = new File(newFilePath+File.separator+"200105.xml");
if(xmlFile.isFile() && xmlFile.exists()){//是文件且存在
List list = readWord(xmlFile);//组装数据、以及文件名称
if(list!=null && list.size()>0){
String wordName = list.get(0).toString();//文件名称
Map dataMap = (Map)list.get(1);//集合数据
String templateFilePath = new File("").getAbsolutePath()+File.separator+"config";//设定为当前文件夹
// System.out.println("模板文件所在目录:"+templateFilePath);
boolean flag = createWord(dataMap,templateFilePath,"word.ftl",classFile.getAbsolutePath(),wordName+".doc");//生成word
if(flag){
result=true;
}else{
errorInfo = "word文件生成失败!";
}
}else{
errorInfo="无法读取"+(newFilePath+File.separator+"200105.xml")+"文件中的数据信息!";
}
}
return result;
}
2、readWord用来读取xml文件组装数据,并返回数据以及word文件名称(因为word文件名称来源于xml文件)。
/***
* 该方法用来组装数据
* @param xmlFile:需要进行解析的xml文件
* */
public List readWord(File xmlFile) {
/** 用于组装word页面需要的数据 */
Map<String, Object> dataMap = new HashMap<String, Object>();
List list = null;
StringBuffer wordName=new StringBuffer();//word文档名称:案件编号+名称+内部编号
try {
//读取XML
SAXReader sax = getSAXReader();
Document doc = sax.read(xmlFile);//读取文档
String fileContent="",appAJ="";
//1、案件编号
Node node = doc.selectSingleNode("//ANJIANBH");
if(node!=null ){
fileContent=node.getText().trim();
}else{
fileContent="";
}
wordName.append(fileContent);
dataMap.put("caseNum",fileContent);//案件编号
//2、名称
node = doc.selectSingleNode("//FAMINGCZMC");
if(node!=null ){
fileContent=node.getText().trim();
}else{
fileContent="";
}
wordName.append(escapeExprSpecialWord(fileContent));//去除特殊字符
dataMap.put("name",fileContent);//名称
//3、内部编号/申请号
fileContent="内部编号:";
node = doc.selectSingleNode("//NEIBUBH");
if(node!=null ){//说明没有内部编号
fileContent="内部编号:"+node.getText().trim();
appAJ = node.getText().trim();
if(appAJ.toUpperCase().startsWith("AJ")){//避免出现小写aj的情况,所以全部转成大写进行比较
//内部编号用最后一个下划线截取
appAJ = appAJ.substring(appAJ.lastIndexOf("_")+1);
}
wordName.append(appAJ);
}else{//那么查找是否有申请号
node = doc.selectSingleNode("//SHENQINGH");
if(node!=null ){
fileContent=node.getText().trim();
wordName.append(fileContent.split(":")[1]);
}
}
dataMap.put("num",fileContent);
//4、提交人姓名或名称
node = doc.selectSingleNode("//XINGMINGHMC");
if(node!=null ){
fileContent=node.getText().trim();
}else{
fileContent="";
}
dataMap.put("proxy",fileContent);
//5、 收到时间
node = doc.selectSingleNode("//QIANMINGSJC");
if(node!=null ){
fileContent=node.getText().trim();
}else{
fileContent="";
}
dataMap.put("time",fileContent);//收到时间
//6、收到文件情况
StringBuffer content= new StringBuffer();
Element element=null;
List<Map<String, Object>> fileList=new ArrayList<Map<String,Object>>();
List<Element> els = doc.selectNodes("//SHOUDAOWJ");
if(els!=null && els.size()>0){
for(int i=0;i<els.size();i++){
Map<String, Object> map=new HashMap<String, Object>();
element = els.get(i);
content.delete(0,content.length());//清空
content.append((i+1)+"、");//序号
node = element.selectSingleNode(".//WENJIANMC");//文件名称
content.append(node.getText().trim()+" ");
node = element.selectSingleNode(".//WENJIANGS");//文件格式
content.append(node.getText().trim()+"格式 ");
node = element.selectSingleNode(".//WENJIANDX");//文件大小
content.append("文件大小"+node.getText().trim());
// System.out.println(content.toString());
map.put("content", content.toString());
fileList.add(map);
}
}else{
Map<String, Object> map=new HashMap<String, Object>();
map.put("content","");
fileList.add(map);
}
dataMap.put("fileList",fileList);
// 落款时间
node = doc.selectSingleNode("//SHOUDAOSJ");
if(node!=null ){
fileContent = node.getText().trim();
}else{
fileContent="";
}
dataMap.put("date",fileContent);//落款时间
list = new ArrayList();
list.add(wordName);
list.add(dataMap);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return list;
}
/**
* 该方法用来获取SXAReader对象
* */
public SAXReader getSAXReader(){
SAXReader saxReader = new SAXReader();
/* 在读取文件时,去掉dtd的验证,可以缩短运行时间 */
try {
// saxReader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);//可能需要网络,所以不用它
saxReader.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE, false); //设置不需要校验头文件
} catch (SAXException e) {
e.printStackTrace();
}
return saxReader;
}
/**
* 转义正则特殊字符 ($()*+.[]?\^{},|/\:?"<>)
* @param keyword
* @return
*/
public String escapeExprSpecialWord(String keyword) {
if(keyword!=null && keyword.trim().length()>0){
String[] fbsArr = {"/","\\",":","*","?","\"","<",">","|", "(", ")","+", "[", "]", "^", "{", "}","、"};
for (String key : fbsArr) {
if (keyword.contains(key)) {
keyword = keyword.replace(key,"");
}
}
}
return keyword;
}
3、createWord用来生成word文档。
/**
* 该方法用来生成word文件
* @param dataMap:数据集合
* @param templateFilePath:模板文件所在目录
* @param templateFileName:模板文件名称
* @param docFilePath:生成的doc文件保存路径
*@param docFileName:生成的doc文件名称:名称+.doc
*/
public static boolean createWord(Map dataMap,
String templateFilePath,String templateFileName,
String docFilePath,String docFileName){
try {
Configuration configuration = new Configuration();//创建配置实例
configuration.setDefaultEncoding("UTF-8");//设置编码
configuration.setDirectoryForTemplateLoading(new File(templateFilePath));//加载模板文件
Template template = configuration.getTemplate(templateFileName);//获取模板
if(docFileName==null || !docFileName.toUpperCase().endsWith(".DOC")){//为空或者不是以doc结尾的,添加后缀名
docFileName = docFileName+".doc";
}
File outFile = new File(docFilePath+File.separator+docFileName);
//如果输出目标文件夹不存在,则创建
if (!outFile.getParentFile().exists()){
outFile.getParentFile().mkdirs();
}
//将模板和数据模型合并生成文件
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));
//生成文件
template.process(dataMap, out);
//关闭流
out.flush();
out.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
三、需要用到的jar包:
freemarker-2.3.16.jar:使用freemarker生成word的主要包
dom4j-1.6.1.jar:解析xml文件的主要包
jaxen-1.1-beta-7.jar:解析xml文件的辅助包
已经上传到附件,有需要的可以下载。
三、需要注意的问题:
a、将word另存为xml得到的xml文件格式很乱,可能只有几行,可以通过格式化工具格式化一下。这样子易读性是增强了,但是可能会影响word格式。我这里有个落款时间就是因为格式化后出现了问题。格式化之前落款时间是居右显示,格式化之后竟然居中了,代码没有变化,可能就是中间出现了空格导致了问题。所以格式化之后最好测试话一下,或者不要格式化。
b、得到的xml文件里的$与参数分开了。譬如原本的word里面写的参数为${content},xml之后${content}被拆成了${,content,和}三部分。具体原因和解决办法可以看看
参考文件,我这就是老出现这个问题,弄了好几次还这样子,不得已只能直接改xml文件。
c、put到map里的参数一定要与xml中写的的参数一致,否则会报错。特别是有list的情况下,别名一定不能忘。我的例子就是${file.content}这个file一定不能忘,否则也会报错。值得庆幸的是,报错很明显,一查就能查不出来。
- 大小: 201.9 KB
分享到:
相关推荐
### 使用FreeMarker生成Word文档 1. **配置FreeMarker**:首先,需要在项目中引入FreeMarker的依赖,例如通过Maven或Gradle添加对应的依赖库。然后,配置FreeMarker的环境,包括设置模板目录、缓存策略等。 2. **...
使用freemarker生成word ,并集成struts2 同时生成及下载文档 资料附有Java源代码和自己总结的使用说明及注意事项 大至预览如下: 1、用word编辑好模板 普通字符串替换为 ${string} 表格循环用标签 姓名:${...
以下是关于如何使用FreeMarker生成Word文件的一些关键知识点: 1. **FreeMarker模板语言**:FreeMarker使用一种简单的模板语言,允许开发者通过定义变量和控制结构(如循环和条件语句)来动态地插入数据。在模板中...
在Java中使用Freemarker生成Word文档的过程主要包括以下几个步骤: 1. **环境配置**:首先,你需要在项目中引入必要的库,包括Apache POI用于处理Word文档,以及Freemarker库。在Maven项目中,可以在pom.xml文件中...
在使用FreeMarker生成Word之前,需要准备一个数据模型,包含要插入到文档中的文本和图片。图片可以作为`byte[]`数组存储,例如: ```java Map, Object> dataModel = new HashMap(); dataModel.put("title", ...
Java利用Freemarker生成Word/PDF是指使用Java语言结合Freemarker模板引擎来生成Word文档或PDF文件的技术。 Freemarker是一个基于Java的模板引擎,它允许开发者使用模板语言来生成文本输出。在本资源中,我们将介绍...
本篇文章将深入探讨如何使用FreeMarker生成Word文档。 1. FreeMarker 概述: FreeMarker 是一个基于模板的Java库,它允许开发者通过模板语言将数据模型与HTML、XML或其他文本格式分离。模板是纯文本文件,包含控制...
### 使用Freemarker生成Word文档的关键技术点解析 #### 一、引言 在实际工作中,经常需要批量生成带有特定格式或数据填充的Word文档,如报表、合同、通知等。传统的手工创建方法效率低下且易出错。利用Java语言...
Springboot项目中: 1. 使用Apache POI 3.9 自定义样式导出Excel文件...2. 使用freemarker动态生成word .doc文档(带图片Word以及复杂格式word) 详细说明见个人博客及 github: https://github.com/DuebassLei/excel-poi
在Java中,生成Word文档通常借助于Apache POI库,而FreeMarker则作为模板引擎,负责数据和模板的结合。Apache POI提供API来操作Word文档,包括创建表格、插入图片等。FreeMarker则可以将动态数据与预先设计好的Word...
3. 使用Freemarker生成Word文档 - 创建Freemarker模板:首先,我们需要创建一个`.ftl`文件,定义好Word文档的结构和样式,使用Freemarker语法(例如`${expression}`)来表示需要动态填充的部分。 - 解析XML数据:...
freemarker根据模板ftl生成word,pdf格式转word,pdf指定位置插入图片
"freemarker_word.zip" 文件集合就是专门针对使用FreeMarker生成Word文档的一个资源包。 该压缩包包含以下关键组件: 1. **Product.ftl**:这是一个FreeMarker模板文件,扩展名为FTL(FreeMarker Template ...
在这个"freemarkerdemo生成word插入图片"的示例中,我们主要探讨如何利用Freemarker来创建Word文档,并且将图片集成到这些文档中。这个过程涉及到几个关键的技术点: 1. **Freemarker基础知识**:Freemarker是一个...
在这个示例中,我们将深入探讨如何使用Freemarker根据XML模板生成Word文档。 首先,你需要了解Freemarker的基本概念。Freemarker是一个基于模板的语言,它的核心是模板文件,模板文件中包含了一系列控制结构(如...
本篇文章将深入探讨如何在Java中使用FreeMarker生成带有盖章的PDF合同文件。 首先,让我们了解FreeMarker的基本概念。FreeMarker是一个基于模板的语言,它与Java代码分离,允许开发者用简单的模板语法来表示数据。...
总结起来,这个入门级的例子展示了如何使用Freemarker生成Word文档的基本步骤。通过模板和数据模型的结合,Freemarker提供了一种灵活的方式来自动生成结构化的文档,大大简化了编程工作。在实际项目中,你可以根据...