Word 文档(.docx)本身就是一个 ZIP 压缩包,里面包含了 XML 文件、图片、样式等资源,但我们通常不直接解析这些内部的 XML,而是使用专门的 Java 库来简化操作。

下面我将介绍两种主流的方法:
- 使用 Apache POI(最常用、最灵活):推荐用于大多数场景,可以精确控制转换过程。
- 使用 docx4j(更专注于 OOXML):同样是强大的库,在处理复杂 Word 结构时表现出色。
使用 Apache POI (推荐)
Apache POI 是处理 Microsoft Office 格式文件的 Java API,对于 Word 文档,它主要使用 XWPF (for .docx) 组件。
添加 Maven 依赖
在你的 pom.xml 文件中添加 Apache POI 的依赖,为了处理 .docx,你需要 poi-ooxml。
<dependencies>
<!-- Apache POI for .docx files -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version> <!-- 建议使用较新版本 -->
</dependency>
<!-- 为了支持 XML 格式化,可能需要 -->
<dependency>
<groupId>javax.xml</groupId>
<artifactId>jaxp-api</artifactId>
<version>1.4.2</version>
</dependency>
</dependencies>
转换逻辑
转换的核心步骤是:

- 使用
XWPFDocument打开.docx文件。 - 遍历文档中的所有元素(段落、表格、图片等)。
- 为每个元素提取文本内容和格式信息。
- 将提取的信息构建成你想要的 XML 结构。
- 将构建好的 XML 字符串写入到
.xml文件中。
示例代码
下面是一个完整的示例,它将一个简单的 .docx 文件转换为一个包含段落和表格信息的 XML 文件。
目标 Word 文档 (sample.docx) 内容示例:
这是第一段标题。
这是第二段正文。
(图片来源网络,侵删)| 列1 | 列2 | | --- | --- | | 数据A1 | 数据A2 | | 数据B1 | 数据B2 |
Java 代码 (WordToXmlConverter.java)
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class WordToXmlConverter {
public static void main(String[] args) {
// 输入和输出文件路径
String docxPath = "sample.docx";
String xmlPath = "output.xml";
try {
// 1. 创建 DOM 文档对象
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
// 2. 创建根元素 <document>
Element rootElement = doc.createElement("document");
doc.appendChild(rootElement);
// 3. 使用 POI 读取 Word 文档
try (FileInputStream fis = new FileInputStream(docxPath);
XWPFDocument document = new XWPFDocument(fis)) {
// 4. 处理段落
for (XWPFParagraph p : document.getParagraphs()) {
if (!p.getParagraphText().trim().isEmpty()) {
Element paragraphElement = doc.createElement("paragraph");
paragraphElement.setTextContent(p.getParagraphText());
rootElement.appendChild(paragraphElement);
}
}
// 5. 处理表格
for (XWPFTable table : document.getTables()) {
Element tableElement = doc.createElement("table");
rootElement.appendChild(tableElement);
for (XWPFTableRow row : table.getRows()) {
Element rowElement = doc.createElement("row");
tableElement.appendChild(rowElement);
for (XWPFTableCell cell : row.getTableCells()) {
Element cellElement = doc.createElement("cell");
// 获取单元格中的所有段落并合并文本
StringBuilder cellText = new StringBuilder();
for (XWPFParagraph p : cell.getParagraphs()) {
cellText.append(p.getParagraphText()).append(" ");
}
cellElement.setTextContent(cellText.toString().trim());
rowElement.appendChild(cellElement);
}
}
}
}
// 6. 将 DOM 对象写入 XML 文件
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); // 美化输出
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(xmlPath));
transformer.transform(source, result);
System.out.println("Word 文件已成功转换为 XML 文件: " + xmlPath);
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行后生成的 output.xml 文件内容:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document>
<paragraph>这是第一段标题。</paragraph>
<paragraph>这是第二段正文。</paragraph>
<paragraph>表格标题</paragraph>
<table>
<row>
<cell>列1 列2 </cell>
</row>
<row>
<cell>数据A1 数据A2 </cell>
</row>
<row>
<cell>数据B1 数据B2 </cell>
</row>
</table>
</document>
POI 进阶:处理更复杂的内容
- 图片:
document.getAllPictures()可以获取图片,然后你可以将图片数据(Base64编码)写入 XML 的特定标签中,或者单独保存图片文件,在 XML 中引用路径。 - 列表:
p.getNumParagraph()和p.getNumILvl()可以用来判断和获取列表信息。 - 样式:
p.getCTP().getPPr()可以获取段落的属性(如居中、加粗等),你可以将这些信息作为 XML 元素的属性。
使用 docx4j
docx4j 是另一个专门用于处理 Open Office XML 格式(如 .docx, .xlsx, .pptx)的库,它在某些方面比 POI 更 OOXML 原生化。
添加 Maven 依赖
<dependencies>
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-core</artifactId>
<version>11.4.4</version> <!-- 建议使用较新版本 -->
</dependency>
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-export-fo</artifactId>
<version>11.4.4</version>
</dependency>
</dependencies>
转换逻辑
docx4j 的转换思路类似,但其 API 设计略有不同。
示例代码
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.*;
import javax.xml.bind.JAXBException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.File;
import java.util.List;
public class Docx4jToXmlConverter {
public static void main(String[] args) {
String docxPath = "sample.docx";
String xmlPath = "output_docx4j.xml";
try {
// 1. 使用 docx4j 加载 Word 文档
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new File(docxPath));
MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
// 2. 获取文档对象 (JAXB 对象)
org.docx4j.wml.Document wmlDocument = (org.docx4j.wml.Document) documentPart.getJaxbElement();
Body body = wmlDocument.getBody();
// 3. 创建 DOM 文档
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("document");
doc.appendChild(rootElement);
// 4. 遍历 Body 中的元素
for (Object o : body.getContent()) {
if (o instanceof P) { // 段落
P paragraph = (P) o;
String text = getTextFromParagraph(paragraph);
if (!text.trim().isEmpty()) {
Element pElement = doc.createElement("paragraph");
pElement.setTextContent(text);
rootElement.appendChild(pElement);
}
} else if (o instanceof Tbl) { // 表格
Tbl table = (Tbl) o;
Element tableElement = doc.createElement("table");
rootElement.appendChild(tableElement);
for (Object rObj : table.getEGContentRowChoice()) {
if (rObj instanceof Tr) {
Tr row = (Tr) rObj;
Element rowElement = doc.createElement("row");
tableElement.appendChild(rowElement);
for (Object cObj : row.getEGContentCellChoice()) {
if (cObj instanceof Tc) {
Tc cell = (Tc) cObj;
Element cellElement = doc.createElement("cell");
String cellText = getTextFromCell(cell);
cellElement.setTextContent(cellText.trim());
rowElement.appendChild(cellElement);
}
}
}
}
}
}
// 5. 写入 XML 文件
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(xmlPath));
transformer.transform(source, result);
System.out.println("Word 文件已成功转换为 XML 文件 (使用 docx4j): " + xmlPath);
} catch (Exception e) {
e.printStackTrace();
}
}
// 辅助方法:从段落中提取纯文本
private static String getTextFromParagraph(P paragraph) {
StringBuilder text = new StringBuilder();
for (Object rObj : paragraph.getEGContentRunChoice()) {
if (rObj instanceof R) {
R run = (R) rObj;
for (Object tObj : run.getEGTextChoice()) {
if (tObj instanceof Text) {
text.append(((Text) tObj).getValue());
}
}
}
}
return text.toString();
}
// 辅助方法:从单元格中提取纯文本
private static String getTextFromCell(Tc cell) {
StringBuilder text = new StringBuilder();
for (P p : cell.getPList()) {
text.append(getTextFromParagraph(p)).append(" ");
}
return text.toString();
}
}
总结与选择
| 特性 | Apache POI | docx4j |
|---|---|---|
| 成熟度 | 非常成熟,社区庞大,资料丰富 | 非常成熟,专注于 OOXML 标准 |
| API 风格 | 面向对象,直接操作 Java 对象 (如 XWPFParagraph) |
基于 JAXB,直接操作 Word 的底层 XML 结构对象 |
| 易用性 | 对于简单的文本提取,API 更直观 | 对于需要精确控制 Word 内部结构(如修改样式、复杂布局)时,更强大 |
| 性能 | 性能良好 | 性能良好,在某些场景下可能略有优势 |
| 推荐场景 | 大多数通用场景,特别是当你只需要提取文本、表格等结构化数据时。 | 需要深度操作 Word 文档内部属性,或者对 OOXML 标准有更精细控制需求的场景。 |
给你的建议:
- 如果你是初学者或需求是“把 Word 里的文字和表格弄出来变成 XML”,请直接选择 Apache POI,它的 API 更友好,学习曲线更平缓。
- 如果你的需求非常复杂,比如需要保留并转换 Word 中的特定样式、字体、颜色、页眉页脚等,并且你对 XML 和 JAXB 有一定了解,docx4j 会是一个更强大的工具。
希望这个详细的指南能帮助你完成 Java 中 Word 到 XML 的转换!

