我有一个代码可以将 ${NAME} 等占位符替换为纯文本。 我使用 docx4j 和 docx4j-search-and-replace-util 来替换占位符。
它工作正常,但现在在“APP_ADDITIONAL_INFO”字段之一中,我需要用 Quill 编辑器中的简单格式化 HTML 替换占位符,例如:
<p><strong>Header</strong></p><p><strong>Text string</strong></p>
结果 .docx 文档包含此 html,而不是此字段的格式化文本。
我研究了这个问题并意识到为此目的有必要使用docx4j-ImportXHTML和JTidy。使用 JTidy,我可以将 HTML 转换为 XHTML,然后 ImportXHTML 将 XHTML 转换为 WordML 格式。
但现在在结果 .docx 中,我看到完整的 WordML 标记而不是格式化文本,从
开始<w:document xmlns:dsp="http://schemas.microsoft.com/office/drawing/2008/diagram"
等等,比如
<w:r><w:rPr><w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman"/><w:b/><w:i w:val="false"/><w:color w:val="000000"/><w:sz w:val="22"/></w:rPr><w:t>Formatted text string</w:t></w:r>
那么,我哪里错了?
我的代码是:
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
XHTMLImporterImpl XHTMLImporter = new XHTMLImporterImpl(wordMLPackage);
BufferedReader br = new BufferedReader(new StringReader(doc.getDescription()));
StringWriter sw = new StringWriter();
Tidy t = new Tidy();
t.setDropEmptyParas(true);
t.setShowWarnings(false); //to hide errors
t.setQuiet(true); //to hide warning
t.setUpperCaseAttrs(false);
t.setXmlOut(true);
t.setUpperCaseTags(false);
t.setInputEncoding("UTF-8");
t.setOutputEncoding("UTF-8");
t.setXmlOut(true);
t.parse(br,sw);
StringBuffer sb = sw.getBuffer();
String strClean = sb.toString();
br.close();
sw.close();
wordMLPackage.getMainDocumentPart().getContent().addAll(XHTMLImporter.convert( strClean, null) );
// the variable that should contain WordML markup
String description = XmlUtils.marshaltoString(wordMLPackage.getMainDocumentPart().getJaxbElement(), true, true);
// map with placeholders and replacing data
Map<String, String> replaceMap = new HashMap<String, String>() {{
put("${APP_EMPLOYEE}", doc.getEmployeeName());
put("${APP_JOB_TITLE}", doc.getJobtitle());
put("${APP_ADDITIONAL_INFO}", description);
}};
byte[] cos = gt.generateDocXDocument(filePath, replaceMap, masterId);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"test.docx\"").body(cos);
在generateDocXDocument方法中:
generateDocXDocument(String filePath, Map <String, String> replaceMap){
byte[] decryptedBytesOfFile = storageService.loadFile(filePath);
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new ByteArrayInputStream(decryptedBytesOfFile));
Docx4JSRUtil.searchAndReplace(wordMLPackage, replaceMap);
OutputStream outputStream = new ByteArrayOutputStream();
Save saver = new Save(wordMLPackage);
saver.save(outputStream);
return ((ByteArrayOutputStream) outputStream).toByteArray();
}
我什至尝试不使用 docx4j-ImportXHTML 和 JTidy,而只是使用 WordML 标记更改占位符,例如:
put("${APP_ADDITIONAL_INFO}", "<w:r><w:rPr><w:rFonts w:ascii=\"Times New Roman\" w:hAnsi=\"Times New Roman\"/><w:b/><w:i w:val=\"false\"/><w:color w:val=\"000000\"/><w:sz w:val=\"22\"/></w:rPr><w:t>Formatted text</w:t></w:r>");
但结果是相同的 - 结果 .docx 文件包含此标记。
正如您所发现的,这是行不通的。您无法以这种方式用标记替换文本。
更好的方法是使用内容控制数据绑定;请参阅 使用 docx4J 生成文档时用 HTML 值替换内容控件