如何用Apache POI的XWPFWordExtractor提取含文本框的DOCX全量文本?
解决DOCX文本框文本提取问题
默认的XWPFWordExtractor只会提取文档正文段落的文本,而文本框属于DOCX中的浮动形状元素,不在其默认扫描范围内,所以会被忽略。要提取全部文本,需要手动遍历文档中的所有形状并提取其中的内容,再和正文文本合并。
完整代码示例
import org.apache.poi.xwpf.usermodel.*; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; import org.openxmlformats.schemas.drawingml.x2006.main.CTShape; import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor; import java.io.InputStream; import java.util.StringJoiner; public class DocxTextExtractor { public static String extractFullText(InputStream inputStream) throws Exception { XWPFDocument doc = new XWPFDocument(inputStream); StringJoiner fullText = new StringJoiner("\n"); // 提取正文文本 XWPFWordExtractor mainExtractor = new XWPFWordExtractor(doc); fullText.add(mainExtractor.getText().trim()); // 提取所有段落中的文本框内容 for (XWPFParagraph paragraph : doc.getParagraphs()) { CTP ctp = paragraph.getCTP(); if (ctp.getAnchorList() != null) { for (CTAnchor anchor : ctp.getAnchorList()) { extractShapeText(anchor.getSp(), fullText); } } } // 可选:提取页眉页脚中的文本框内容 for (XWPFHeader header : doc.getHeaders()) { extractTextFromHeaderFooter(header, fullText); } for (XWPFFooter footer : doc.getFooters()) { extractTextFromHeaderFooter(footer, fullText); } doc.close(); return fullText.toString().trim(); } private static void extractShapeText(CTShape shape, StringJoiner textJoiner) { if (shape.getTxBody() != null) { // 将形状内的文本主体转换为临时段落,复用XWPFWordExtractor提取文本 XWPFDocument tempDoc = new XWPFDocument(); XWPFParagraph tempPara = tempDoc.createParagraph(); tempPara.getCTP().set(shape.getTxBody().getPArray(0)); XWPFWordExtractor tempExtractor = new XWPFWordExtractor(tempDoc); String shapeText = tempExtractor.getText().trim(); if (!shapeText.isEmpty()) { textJoiner.add(shapeText); } try { tempDoc.close(); } catch (Exception e) { // 忽略关闭异常 } } } private static void extractTextFromHeaderFooter(XWPFHeaderFooter headerFooter, StringJoiner textJoiner) { for (XWPFParagraph paragraph : headerFooter.getParagraphs()) { CTP ctp = paragraph.getCTP(); if (ctp.getAnchorList() != null) { for (CTAnchor anchor : ctp.getAnchorList()) { extractShapeText(anchor.getSp(), textJoiner); } } } } }
代码说明
- 主方法
extractFullText:先提取常规正文文本,再遍历所有段落的锚点元素(文本框的载体),提取其中的文本内容;同时支持可选提取页眉页脚内的文本框内容。 extractShapeText方法:通过临时创建XWPFDocument和段落,复用POI的文本提取逻辑,避免手动解析复杂的XML结构。- 针对DOCX结构:文本框在DOCX中是以锚点(
CTAnchor)形式绑定到段落上的,所以需要遍历每个段落的锚点列表来找到文本框。
注意:该代码适配POI 5.2.3版本,不同版本的XML Schema类可能存在细微差异,请根据实际版本调整。
内容的提问来源于stack exchange,提问作者Lako12
相关产品推荐
相关产品推荐

