求助:将MS Word格式XML数据存入Apache POI的XWPFDocument报错
问题描述
尝试将MS Word格式的XML数据存入Apache POI的XWPFDocument时执行出错,以下是编写的代码,求正确读取并存储这类文件的方法。
原代码
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; public class WordMerger { public static void main(String[] args) { try { // Open the first document XWPFDocument doc1 = new XWPFDocument(new FileInputStream("document1.xml")); // Open the second document XWPFDocument doc2 = new XWPFDocument(new FileInputStream("document2.xml")); // Iterate through the paragraphs of the second document for (XWPFParagraph p : doc2.getParagraphs()) { // Create a new paragraph in the first document XWPFParagraph newParagraph = doc1.createParagraph(); // Iterate through the runs of the current paragraph in the second document for (XWPFRun r : p.getRuns()) { // Create a new run in the new paragraph of the first document XWPFRun newRun = newParagraph.createRun(); // Copy the text and formatting of the current run to the new run newRun.setText(r.getText(0)); newRun.setBold(r.isBold()); newRun.setItalic(r.isItalic()); newRun.setUnderline(r.getUnderline()); newRun.setColor(r.getColor()); newRun.setFontFamily(r.getFontFamily()); newRun.setFontSize(r.getFontSize()); } } // Save the merged document doc1.write(new FileOutputStream("merged_document.xml")); // Close the documents doc1.close(); doc2.close(); System.out.println("Documents merged successfully!"); } catch (IOException e) { e.printStackTrace(); } } }
问题分析与解决方案
1. 基础语法错误修正
原代码中注释未添加//,会直接导致编译失败,已在上述代码中补全。
2. XML文件类型适配问题
XWPFDocument默认仅支持完整的OOXML格式文件(.docx)或Flat OPC XML格式(将整个docx包打包为单个XML),如果你的XML属于以下两种情况,需要针对性处理:
情况A:XML是docx解压后的单个document.xml
这种XML只是docx包中的核心内容,缺少OOXML所需的包结构和元数据,无法直接用XWPFDocument读取,需先构建完整的OPCPackage:
import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.OutputStream; // 构建临时OPCPackage OPCPackage pkg = OPCPackage.create(new File("temp.docx")); // 将单个document.xml添加到OOXML包的正确路径 PackagePart docPart = pkg.createPart( new org.apache.poi.openxml4j.opc.PackageName("/word/document.xml"), "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" ); // 写入XML内容 try (OutputStream out = docPart.getOutputStream()) { FileInputStream in = new FileInputStream("document1.xml"); byte[] buffer = new byte[1024]; int len; while ((len = in.read(buffer)) != -1) { out.write(buffer, 0, len); } in.close(); } // 添加必要的样式关系(避免格式丢失) pkg.getPartsByName("/word/document.xml").get(0).addRelationship( new org.apache.poi.openxml4j.opc.PackageName("/word/styles.xml"), PackageRelationshipTypes.STYLES, "styles" ); // 从OPCPackage创建XWPFDocument XWPFDocument doc1 = new XWPFDocument(pkg);
情况B:XML是Word 2003的WordML格式
这种旧格式XML需先转换为docx格式再处理,可使用Apache POI的WordToXWPFConverter:
import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.converter.WordToXWPFConverter; // 读取WordML文档 HWPFDocument hwpfDoc = new HWPFDocument(new FileInputStream("document1.xml")); // 转换为XWPFDocument XWPFDocument doc1 = new XWPFDocument(); WordToXWPFConverter converter = new WordToXWPFConverter(doc1); converter.processDocument(hwpfDoc); hwpfDoc.close();
3. 合并逻辑优化
原代码仅复制了Run的基础格式,可补充段落格式复制以保留更多排版信息:
// 复制段落对齐、缩进、间距等格式 newParagraph.setAlignment(p.getAlignment()); newParagraph.setIndentationLeft(p.getIndentationLeft()); newParagraph.setIndentationRight(p.getIndentationRight()); newParagraph.setSpacingBefore(p.getSpacingBefore()); newParagraph.setSpacingAfter(p.getSpacingAfter());
内容的提问来源于stack exchange,提问作者Shubham A
相关产品推荐
相关产品推荐

