我的Word模板很少,我的要求是使用Java根据用户输入替换文档中的一些单词/占位符。我尝试了很多库,包括2-3个版本的docx4j
,但没有什么效果很好,它们都没有做任何事情!
我知道之前已经问过这个问题,但我尝试了所有我知道的选项。那么,使用什么java库我可以“真正”替换/编辑这些模板?我倾向于“易于使用/几行代码”类型库。
我正在使用Java 8,我的MS Word模板在MS Word 2007中。
更新
此代码是使用SO成员Joop Eggen
public Main() throws URISyntaxException, IOException, ParserConfigurationException, SAXException
{
URI docxUri = new URI("C:/Users/Yohan/Desktop/yohan.docx");
Map<String, String> zipProperties = new HashMap<>();
zipProperties.put("encoding", "UTF-8");
FileSystem zipFS = FileSystems.newFileSystem(docxUri, zipProperties);
Path documentXmlPath = zipFS.getPath("/word/document.xml");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(Files.newInputStream(documentXmlPath));
byte[] content = Files.readAllBytes(documentXmlPath);
String xml = new String(content, StandardCharsets.UTF_8);
//xml = xml.replace("#DATE#", "2014-09-24");
xml = xml.replace("#NAME#", StringEscapeUtils.escapeXml("Sniper"));
content = xml.getBytes(StandardCharsets.UTF_8);
Files.write(documentXmlPath, content);
}
然而,这会返回以下错误
java.nio.file.ProviderNotFoundException: Provider "C" Not found
at: java.nio.file.FileSystems.newFileSystem(FileSystems.java:341) at java.nio.file.FileSystems.newFileSystem(FileSystems.java:341)
at java.nio.fileFileSystems.newFileSystem(FileSystems.java:276)
答案 0 :(得分:3)
可以使用docx(带有XML和其他文件的zip)java zip文件系统和XML或文本处理。
URI docxUri = ,,, // "jar:file:/C:/... .docx"
Map<String, String> zipProperties = new HashMap<>();
zipProperties.put("encoding", "UTF-8");
try (FileSystem zipFS = FileSystems.newFileSystem(docxUri, zipProperties)) {
Path documentXmlPath = zipFS.getPath("/word/document.xml");
使用XML时:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(Files.newInputStream(documentXmlPath));
//Element root = doc.getDocumentElement();
然后,您可以使用XPath查找位置,并再次写回XML。
甚至可能是您不需要XML但可以取代占位符:
byte[] content = Files.readAllBytes(documentXmlPath);
String xml = new String(content, StandardCharsets.UTF_8);
xml = xml.replace("#DATE#", "2014-09-24");
xml = xml.replace("#NAME#", StringEscapeUtils.escapeXml("Sniper")));
...
content = xml.getBytes(StandardCharsets.UTF_8);
Files.delete(documentXmlPath);
Files.write(documentXmlPath, content);
要进行快速开发,请将.docx的副本重命名为带.zip文件扩展名的名称,然后检查文件。
File.write
应该已经应用了StandardOpenOption.TRUNCATE_EXISTING,但我添加了Files.delete
,因为发生了一些错误。见评论。
答案 1 :(得分:3)
试试Apache POI。 POI
可以与doc
和docx
一起使用,但docx
更有文档记录,因此可以更好地支持它。
UPD :您可以使用使用POI的XDocReport。另外,我建议将xlsx
用于模板,因为它更适合more documented
答案 2 :(得分:2)
我已经花了几天时间讨论这个问题,直到我发现产生差异的是FileSystem实例上的try-with-resources
,出现在Joop Eggen的代码片段中,但没有问题片段:
try (FileSystem zipFS = FileSystems.newFileSystem(docxUri, zipProperties))
如果没有此try-with-resources
块,则FileSystem
资源将不会关闭(如Java tutorial中所述),并且未修改word文档。
答案 3 :(得分:0)
稍微退一步,有大约4种不同的方法来编辑单词/占位符:
在选择之前,您应该决定是否还需要能够处理:
如果您需要这些,那么MERGEFIELD或DOCPROPERTY字段可能已经输出(尽管您也可以使用IF字段,如果您可以找到支持它们的库)。并且添加图像使得DOM / SAX操作在其他一个答案中被提倡,更加容易和容易出错。
要考虑的其他事项是: