问题描述
我是Apache VeLocity的新手,我想知道什么是评估上下文的正确方法。这是我的情况:
我想打开一个用作模板的.docx
文件,用Apache VeLocity
替换其中的一些单词,然后将结果保存到新的.docx
文件中。为此,我的代码如下:
public static void main(String[] args) {
VeLocity.init();
final VeLocityContext context = new VeLocityContext();
context.put("city","Firenze");
context.put("user","Federico");
context.put("date","23/09/20");
context.put("op","Mario Rossi");
ArrayList<String> list = new ArrayList<String>();
list.add("Data futura");
list.add("Scrittura indecifrabile");
context.put("list",list);
String name = "tempWord.docx";
List<XWPFParagraph> paragraphs;
try {
paragraphs = readDocxFile(name);
XWPFDocument doc = new XWPFDocument();
final FileOutputStream fos = new FileOutputStream(new File("outFile.docx"));
for(XWPFParagraph para : paragraphs) {
StringWriter sw = new StringWriter();
System.out.println(para.getText());
VeLocity.evaluate(context,sw,"test1",para.getText());
XWPFParagraph par = doc.createParagraph();
XWPFRun run = par.createRun();
run.setText(sw.toString());
}
doc.write(fos);
fos.close();
} catch(Exception rnfe) {
rnfe.printstacktrace();
}
}
其中readDocxFile()
是我已经定义并且可以完美工作的方法。给我担心的是给定此模板:
${city},${date}
Gentile ${user},Con la seguente la informiamo che non abbiamo potuto processare la sua richiesta a causa dei seguenti errori:
#foreach(${name} in ${list})
${name}
#end
La preghiamo dunque di correggere e sottoporre nuovamente il modulo entro e non oltre la data di scadenza.
Cordiali saluti,${op}
我收到此错误
1606 [main] ERROR org.apache.veLocity.parser - test1: Encountered "<EOF>" at line 1,column 29.
它在解析#foreach
循环时发生,并且似乎与VeLocity.evaluate()
方法有关,因为如果我创建一个tmp.txt
文件并将其与VeLocity模板一起用作VeLocity模板, VeLocity.mergeTemplate()
方法使代码正确运行。这种方法的问题在于,我不想每次都要评估上下文时都存储.txt
,而必须保持原始文件格式。
据我了解,evaluate()
逐行评估,因此显然#foreach
块评估不正确。
我知道Apache POI
和docx4j
一样也可以执行上下文替换,但是我必须使用VeLocity。
如何正确评估上下文?
解决方法
我会尝试使用自定义分隔符合并所有段落,然后在该分隔符上拆分结果以重建段落。类似于:
try {
paragraphs = readDocxFile(name);
XWPFDocument doc = new XWPFDocument();
final FileOutputStream fos = new FileOutputStream(new File("outFile.docx"));
StringWriter sw = new StringWriter();
String separator = "_PARA_";
for(XWPFParagraph para : paragraphs) {
System.out.println(para.getText());
sw.append(para.getText());
sw.append(separator);
}
StringWriter rst = new StringWriter();
Velocity.evaluate(context,rst,"test1",sw.toString);
for (String para : rst.toString().split(separator))
XWPFParagraph par = doc.createParagraph();
XWPFRun run = par.createRun();
run.setText(para);
}
doc.write(fos);
fos.close();
} catch(Exception rnfe) {
rnfe.printStackTrace();
}
但是,您可能知道,通过将段落前后转换为这样的文本,您很容易出现宽松的格式标签,而不必谈论标题,表格,枚举等。它应该适合标准正文文字。