Java读取DOCX文件本质是将其作为ZIP包解析,因DOCX基于OOXML标准,内含document.xml等XML文件;可用Apache POI的XWPFDocument获取PackagePart读取XML流,或用java.util.zip手动解压并解析,须开启命名空间支持。
Java 读取 DOCX 文件中的 XML 内容,本质是把 DOCX 当作 ZIP 压缩包来解析,因为 .docx 是基于 Office Open XML(OOXML)标准的 ZIP 归档,里面包含多个 XML 文件(如 document.xml、styles.xml、header1.xml 等)。
Apache POI 的 XWPF 模块封装了对 DOCX 的读写,但底层仍依赖对 XML 的访问。若需直接操作原始 XML,可结合 POI 获取底层 PackagePart 或手动解压:
XWPFDocument 加载文件后,通过 getPackage().getPartsByName(Pattern.compile("word/document\\.xml")) 获取对应 XML 部分getInputStream() 得到 XML 字节流,再用 DocumentBuilder 或 SAXParser 解析成 DOM/SAX 树XWPFDocument doc = new XWPFDocument(new FileInputStream("test.docx"));
PackagePart part = doc.getPacka
ge().getPartsByName(Pattern.compile("word/document\\.xml")).get(0);
Document xml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(part.getInputStream());
System.out.println(xml.getDocumentElement().getNodeName()); // 通常是 w:documentDOCX 就是 ZIP,可用 Java 原生 java.util.zip 打开,适合读取 styles.xml、numbering.xml 等非正文内容:
ZipFile 打开 .docx 文件"word/styles.xml" 或 "word/numbering.xml"
ZipEntry.getInputStream() 读取 XML 流,再交给 XML 解析器处理w:),解析时需开启命名空间支持(factory.setNamespaceAware(true))Office Open XML 使用严格命名空间,典型前缀有:
w: 主文档结构(paragraph、run、text)r: 关系(hyperlink、image reference)a: 绘图(drawing、shape)getElementsByTagNameNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "p") 而非 getElementsByTagName("w:p")
XML 结构嵌套深、命名空间敏感、可能含 CDATA 或转义字符,用正则提取文本或标签容易出错:
content.replaceAll("(.*?) ", "$1") —— 不处理嵌套、命名空间、换行、实体编码
XWPFDocument.getText() 更简单可靠基本上就这些。关键点是:DOCX 是 ZIP → XML 在里面 → 用 POI 或原生 ZIP + XML 解析器读取 → 别忽略命名空间。