导读:本期聚焦于小伙伴创作的《如何用Java解析XML并借助Apache POI生成Excel文件?》,敬请观看详情。把业务系统导出的XML报文转成可筛选的Excel报表,常常卡在节点遍历与单元格样式这两步。本文从DOM解析入手,说明如何用DocumentBuilder读取标签与属性,再将抽取的数据通过Apache POI的XSSFWorkbook写入xlsx。我们会对比SAX与DOM的适用场景,给出避免内存溢出的流式写法,并附上完整代码示例,帮你少走弯路。

在企业级开发中,经常需要把第三方系统返回的XML数据转换成Excel报表供运营或财务使用。Java生态里,解析XML有DOM、SAX、StAX等多种方式,而生成Excel最成熟的库莫过于Apache POI。本文以一个订单XML为例,演示如何解析后写出xlsx文件。

如何用Java解析XML并借助Apache POI生成Excel文件?

一、XML解析方案选择

DOM解析会把整个文档加载进内存,形成树结构,适合几兆以内的小文件,代码直观、调试方便。SAX则是事件驱动,边读边处理,内存占用低,但写起来要自己维护状态机。对于大多数后台报表任务,文件不超过几十兆,用DOM更省心。

下面先用标准JDK自带的DocumentBuilder完成解析,不需要引入额外依赖。我们需要处理命名空间时要格外小心,否则getElementsByTagName可能返回空列表。建议先打印根节点名称确认结构。

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Element;
import java.io.File;

public class XmlReader {
    public Document parse(String path) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        // 忽略命名空间,简化查询
        factory.setNamespaceAware(false);
        DocumentBuilder builder = factory.newDocumentBuilder();
        return builder.parse(new File(path));
    }

    public void printOrders(Document doc) {
        NodeList nodes = doc.getElementsByTagName("order");
        for (int i = 0; i < nodes.getLength(); i++) {
            Element e = (Element) nodes.item(i);
            String id = e.getAttribute("id");
            String amount = e.getElementsByTagName("amount").item(0).getTextContent();
            System.out.println("订单号:" + id + " 金额:" + amount);
        }
    }
}

二、Apache POI写Excel基础

Apache POI的XSSF模块对应Office Open XML格式(xlsx)。核心类是XSSFWorkbook、XSSFSheet、XSSFRow和XSSFCell。创建工作簿后,先建sheet,再循环建行与单元格,最后用FileOutputStream写出。

需要注意的是,POI在写出大文件时默认会把所有数据放内存,可能触发OOM。如果数据量超过五万行,应使用SXSSFWorkbook,它用临时文件做滑动窗口。下面的例子先用普通XSSFWorkbook演示基本API。

import org.apache.poi.xssf.usermodel.*;
import java.io.FileOutputStream;

public class ExcelWriter {
    public void write(java.util.List<String[]> data, String out) throws Exception {
        XSSFWorkbook wb = new XSSFWorkbook();
        XSSFSheet sheet = wb.createSheet("订单表");
        // 表头样式
        XSSFCellStyle headStyle = wb.createCellStyle();
        XSSFFont font = wb.createFont();
        font.setBold(true);
        headStyle.setFont(font);

        for (int r = 0; r < data.size(); r++) {
            XSSFRow row = sheet.createRow(r);
            String[] cols = data.get(r);
            for (int c = 0; c < cols.length; c++) {
                XSSFCell cell = row.createCell(c);
                cell.setCellValue(cols[c]);
                if (r == 0) {
                    cell.setCellStyle(headStyle);
                }
            }
        }
        try (FileOutputStream fos = new FileOutputStream(out)) {
            wb.write(fos);
        }
        wb.close();
    }
}

三、将解析与生成串起来

真实场景中,我们会先解析XML拿到订单集合,再组装成二维数组传给ExcelWriter。这样职责分离,后续若改成分库分表查询也容易替换数据源。下面的代码演示整合过程,并加了简单异常处理。

如果XML里日期是字符串,可以用SimpleDateFormat转成Date再写入,POI支持setCellValue(Date)并配合日期格式。另外,中文乱码通常源于文件读取编码,建议用InputStreamReader指定UTF-8。

import org.w3c.dom.*;
import java.util.*;

public class XmlToExcel {
    public static void main(String[] args) {
        try {
            XmlReader reader = new XmlReader();
            Document doc = reader.parse("orders.xml");
            List<String[]> rows = new ArrayList<>();
            rows.add(new String[]{"订单号", "金额", "客户"});
            NodeList list = doc.getElementsByTagName("order");
            for (int i = 0; i < list.getLength(); i++) {
                Element e = (Element) list.item(i);
                String id = e.getAttribute("id");
                String amount = e.getElementsByTagName("amount").item(0).getTextContent();
                String cust = e.getElementsByTagName("customer").item(0).getTextContent();
                rows.add(new String[]{id, amount, cust});
            }
            new ExcelWriter().write(rows, "orders.xlsx");
            System.out.println("生成完成");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

四、性能与避坑要点

当XML体积大且只需提取部分字段时,DOM会浪费内存。可改用SAX,在startElement里判断标签名并暂存,endElement里输出一行。与之对应,Excel侧使用SXSSFWorkbook,设置窗口为1000行,旧行自动刷盘。

另一个常见坑是POI依赖的commons-compress或stax-api版本冲突,导致NoSuchMethodError。建议在Maven里锁定poi-ooxml版本,并排除旧传递依赖。此外,写完workbook必须close,否则临时文件不清理,磁盘会被占满。

解析方式内存占用适用规模
DOM小于50MB
SAX数百MB
StAX流式处理

掌握上述组合,你就能用Java稳定地把各类XML单据转成业务人员喜欢的Excel了。

Java_XML解析Apache_POIExcel生成修改时间:2026-08-08 09:33:28

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。