Word 的 XML 格式
现代的 .docx 文件本质上是一个 ZIP 压缩包,解压后,你会发现它包含多个 XML 文件,其中最重要的是:

document.xml: 文档的主要内容,包括段落、表格、图片等。styles.xml: 定义文档中的样式(如标题、正文、加粗等)。header1.xml,footer1.xml: 页眉和页脚。[Content_Types].xml: 描述包内所有文件的类型。
"生成 Word XML" 可以理解为以下几种操作:
- 直接操作 XML 字符串:手动构建符合
document.xml格式的字符串,然后打包成.docx。 - 使用库操作 XML 对象:使用 XML 解析/生成库(如
dom4j)来构建 XML 对象,再转换为字符串并打包。 - 使用高级 Word 库:使用专门处理
.docx的库(如 Apache POI),它们在底层也操作 XML,但为你提供了更高层次的、面向对象的 API,让你无需关心复杂的 XML 结构。
直接拼接 XML 字符串 (不推荐,但原理重要)
这种方法让你完全控制 XML 的每一个字符,但非常繁琐且容易出错,它适合于生成结构极其简单的、固定格式的文档。
原理:
- 创建一个符合
document.xml结构的字符串。 - 将此字符串和其他必需的 XML 文件(如
styles.xml)一起打包成一个 ZIP 文件。 - 将 ZIP 文件的后缀名改为
.docx。
缺点:

- 极易出错:XML 标签必须严格匹配,命名空间不能错。
- 维护困难:如果需求变化(比如改个样式),需要手动修改一大串字符串。
- 功能有限:很难处理复杂元素,如图片、复杂表格、页眉页脚等。
示例代码:
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class SimpleWordXmlGenerator {
public static void main(String[] args) {
// 1. 构建 document.xml 的内容
String documentXmlContent = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
"<w:document xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">" +
" <w:body>" +
" <w:p>" + // 开始一个段落
" <w:r>" + // 开始一个文本运行
" <w:t>这是一个通过直接拼接 XML 生成的 Word 文档。</w:t>" + // 文本内容
" </w:r>" +
" <w:r>" +
" <w:rPr><w:b/></w:rPr>" + // 文本属性:加粗
" <w:t>这段文字是粗体的。</w:t>" +
" </w:r>" +
" </w:p>" +
" <w:p>" +
" <w:r>" +
" <w:t>当前时间: </w:t>" +
" </w:r>" +
" <w:r>" +
" <w:t>" + new java.util.Date() + "</w:t>" + // 插入动态内容
" </w:r>" +
" </w:p>" +
" </w:body>" +
"</w:document>";
// 2. 定义要打包进 .docx 的文件
// 一个最简 .docx 至少需要 [Content_Types].xml 和 word/_rels/document.xml.rels
// 以及 word/document.xml 和 word/styles.xml
// 为了简化,我们只生成核心文件,其他文件可以使用一个“空模板”来获取。
// 3. 将文件打包成 .docx
String outputFileName = "SimpleGeneratedDocument.docx";
try (FileOutputStream fos = new FileOutputStream(outputFileName);
ZipOutputStream zos = new ZipOutputStream(fos, StandardCharsets.UTF_8)) {
// 添加 document.xml
zos.putNextEntry(new ZipEntry("word/document.xml"));
zos.write(documentXmlContent.getBytes(StandardCharsets.UTF_8));
zos.closeEntry();
// 添加 [Content_Types].xml (可以从一个模板中复制)
String contentTypes = "[Content_Types].xml 内容..."; // 这里应该是一个完整的 [Content_Types].xml 文件内容
zos.putNextEntry(new ZipEntry("[Content_Types].xml"));
zos.write(contentTypes.getBytes(StandardCharsets.UTF_8));
zos.closeEntry();
// ... 还需要添加 styles.xml, fontTable.xml 等,否则文件会损坏。
// 这非常复杂,因此强烈建议使用库。
System.out.println("Word 文档 " + outputFileName + " 生成成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
注意:这个例子为了简化,省略了其他必需的 XML 文件,直接运行这个代码生成的文件可能无法正常打开,这充分说明了直接操作 XML 的复杂性。
使用 XML 库 (如 dom4j) (推荐用于复杂定制)
这种方法比直接拼接字符串更健壮、更易于维护,你使用 dom4j 这样的库来构建 XML DOM 树,然后将其序列化为字符串,再打包成 .docx。
优点:

- 结构清晰:代码与 XML 结构一一对应,易于阅读和维护。
- 不易出错:库会处理 XML 转义、命名空间等问题。
- 功能强大:可以方便地构建复杂的 XML 结构。
缺点:
- 你仍然需要了解 Word 的 XML 结构(
document.xml等)。 - 仍然需要手动处理
.docx的打包过程(添加其他必需文件)。
示例代码:
添加 dom4j 依赖:
<!-- pom.xml -->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.4</version>
</dependency>
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class Dom4jWordGenerator {
public static void main(String[] args) {
// 1. 使用 dom4j 创建 document.xml
Document document = DocumentHelper.createDocument();
Element rootElement = document.addElement("document", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
Element body = rootElement.addElement("body");
// 创建第一个段落
Element p1 = body.addElement("p");
Element r1 = p1.addElement("r");
Element t1 = r1.addElement("t");
t1.setText("这是使用 dom4j 生成的 Word 文档。");
// 创建第二个段落,带加粗样式
Element p2 = body.addElement("p");
Element r2 = p2.addElement("r");
// 添加文本属性(加粗)
Element rPr = r2.addElement("rPr");
rPr.addElement("b"); // <w:b/>
Element t2 = r2.addElement("t");
t2.setText("这个段落是粗体的。");
// 2. 将 DOM 对象转换为格式化的 XML 字符串
StringWriter stringWriter = new StringWriter();
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
XMLWriter xmlWriter = new XMLWriter(stringWriter, format);
try {
xmlWriter.write(document);
} catch (IOException e) {
e.printStackTrace();
}
String documentXmlContent = stringWriter.toString();
// 3. 打包成 .docx (同方法一,需要其他文件)
String outputFileName = "Dom4jGeneratedDocument.docx";
try (FileOutputStream fos = new FileOutputStream(outputFileName);
ZipOutputStream zos = new ZipOutputStream(fos, StandardCharsets.UTF_8)) {
zos.putNextEntry(new ZipEntry("word/document.xml"));
zos.write(documentXmlContent.getBytes(StandardCharsets.UTF_8));
zos.closeEntry();
System.out.println("Word 文档 " + outputFileName + " 生成成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
注意:这个例子同样简化了打包过程,在实际项目中,你可能需要一个完整的
.docx模板,从中提取出styles.xml,[Content_Types].xml等文件,然后替换掉document.xml。
使用 Apache POI (强烈推荐)
这是目前 Java 生态中最流行、功能最强大的 Word 文档操作库,它封装了所有底层的 XML 细节,提供了一套简单易用的 Java API。
优点:
- API 简单直观:你操作的是
XWPFDocument,XWPFParagraph,XWPFRun等对象,而不是 XML 标签。 - 功能全面:支持段落、表格、列表、图片、页眉页脚、页码、样式等几乎所有 Word 功能。
- 社区活跃:文档丰富,遇到问题容易找到解决方案。
- 无需关心 XML:你只需要关心 Word 文档的逻辑结构,库会帮你处理好所有底层的 XML 和 ZIP 打包。
缺点:
- 对于超大型文档,可能会有性能问题。
- 需要引入额外的依赖。
示例代码:
添加 Apache POI 依赖:
<!-- pom.xml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.util.Units;
import java.io.FileOutputStream;
import java.io.IOException;
public class ApachePoiWordGenerator {
public static void main(String[] args) {
// 1. 创建一个空的 Word 文档对象
try (XWPFDocument document = new XWPFDocument()) {
// 2. 创建一个段落
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
// 3. 向段落中添加文本和格式
run.setText("这是使用 Apache POI 生成的 Word 文档。");
run.setBold(true); // 设置为粗体
run.setFontSize(14); // 设置字体大小
run.setColor("FF0000"); // 设置字体颜色 (红色)
// 4. 创建第二个段落
XWPFParagraph paragraph2 = document.createParagraph();
XWPFRun run2 = paragraph2.createRun();
run2.setText("POI 非常强大,可以轻松处理复杂的文档结构。");
run2.addBreak(); // 换行
run2.setText("比如添加一个列表:");
// 5. 创建一个列表
XWPFParagraph listParagraph = document.createParagraph();
listParagraph.setNumID(listParagraph.getCTP().addNewPPr().addNewNumPr().addNewNumId());
listParagraph.getCTP().getPPr().getNumPr().getNumId().setVal(1L); // 假设列表ID为1
XWPFRun listRun = listParagraph.createRun();
listRun.setText("列表项 1");
XWPFParagraph listParagraph2 = document.createParagraph();
listParagraph2.setNumID(listParagraph2.getCTP().addNewPPr().addNewNumPr().addNewNumId());
listParagraph2.getCTP().getPPr().getNumPr().getNumId().setVal(1L);
XWPFRun listRun2 = listParagraph2.createRun();
listRun2.setText("列表项 2");
// 6. 创建一个表格
XWPFTable table = document.createTable();
XWPFTableRow tableRowOne = table.getRow(0);
tableRowOne.getCell(0).setText("姓名");
tableRowOne.addNewTableCell().setText("年龄");
tableRowOne.addNewTableCell().setText("城市");
XWPFTableRow tableRowTwo = table.createRow();
tableRowTwo.getCell(0).setText("张三");
tableRowTwo.getCell(1).setText("30");
tableRowTwo.getCell(2).setText("北京");
// 7. 将文档写入 .docx 文件
try (FileOutputStream out = new FileOutputStream("ApachePoiGeneratedDocument.docx")) {
document.write(out);
System.out.println("Word 文档 ApachePoiGeneratedDocument.docx 生成成功!");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
这个例子展示了 POI 的强大之处,几行代码就完成了包含格式文本、列表和表格的复杂文档生成,代码可读性极高。
总结与对比
| 特性 | 直接拼接 XML | 使用 dom4j |
使用 Apache POI |
|---|---|---|---|
| 易用性 | 极差 | 中等 | 极佳 |
| 可维护性 | 极差 | 良好 | 优秀 |
| 功能丰富度 | 极差 | 中等 | 非常全面 |
| 性能 | 取决于字符串拼接 | 取决于 XML 库 | 良好,适合大多数场景 |
| 学习曲线 | 需要深入了解 Word XML 结构 | 需要了解 Word XML 和 XML 库 | API 简单,容易上手 |
| 推荐场景 | 几乎不推荐,仅用于学习 XML 结构 | 需要高度定制化 XML 且 POI 无法满足的极端情况 | 绝大多数 Java 生成 Word 文档的首选方案 |
最终建议
对于 99% 的应用场景,强烈推荐使用 Apache POI,它能让你从复杂的底层 XML 细节中解放出来,专注于业务逻辑,极大地提高开发效率和代码质量。
只有在有极其特殊的需求,例如需要生成一个 POI 当前版本不支持或支持得不好的特定 Word 功能,并且你愿意深入研究 Word 的底层 XML 结构时,才考虑使用方法二(dom4j),而方法一(直接拼接字符串)仅作为理解 Word 文件格式的入门示例,不应在生产项目中使用。
