当前位置:首页 > 后端开发 > 正文

如何用Java解析XML文件?

Java解析XML文件常用DOM、SAX或StAX方式:DOM加载整个文档到内存树结构;SAX基于事件流逐行解析节省内存;StAX提供双向解析,也可用JAXB实现对象绑定或第三方库如JDOM/DOM4J简化操作。

使用Java解析XML文件的完整指南

XML(可扩展标记语言)是存储和传输结构化数据的通用格式,在Java开发中,解析XML是常见需求,例如处理配置文件、API响应或数据交换,本文将详细介绍五种主流解析方法,并提供可运行的代码示例。


XML解析的核心方法

Java解析XML主要分为两类模型:

  1. DOM(文档对象模型)
    一次性加载整个XML到内存,生成树形结构,适合小型文件,支持随机访问。

    • 优点:直观易用,可修改XML结构
    • 缺点:内存占用高
  2. SAX/StAX(流式模型)
    基于事件驱动,按顺序读取XML节点。

    如何用Java解析XML文件?  第1张

    • 优点:内存效率高,适合大文件
    • 缺点:只能单向遍历

DOM解析(标准库)

import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.File;
public class DOMParser {
    public static void main(String[] args) throws Exception {
        // 1. 创建解析器工厂
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        // 2. 防止XXE攻击(安全关键步骤)
        factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        // 3. 解析XML文件
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.parse(new File("data.xml"));
        doc.getDocumentElement().normalize();  // 标准化文档
        // 4. 遍历节点
        NodeList nodeList = doc.getElementsByTagName("book");
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element element = (Element) node;
                String title = element.getElementsByTagName("title")
                                     .item(0).getTextContent();
                System.out.println("书名: " + title);
            }
        }
    }
}

SAX解析(标准库)

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.*;
public class SAXParser extends DefaultHandler {
    private boolean isTitle = false;
    public void startElement(String uri, String localName, 
                             String qName, Attributes attributes) {
        if (qName.equalsIgnoreCase("title")) {
            isTitle = true;
        }
    }
    public void characters(char[] ch, int start, int length) {
        if (isTitle) {
            System.out.println("书名: " + new String(ch, start, length));
            isTitle = false;
        }
    }
    public static void main(String[] args) throws Exception {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser saxParser = factory.newSAXParser();
        saxParser.parse("data.xml", new SAXParser());  // 事件驱动解析
    }
}

JDOM解析(第三方库)

步骤:

  1. 添加Maven依赖:

    <dependency>
      <groupId>org.jdom</groupId>
      <artifactId>jdom2</artifactId>
      <version>2.0.6</version>
    </dependency>
  2. 代码实现:

    import org.jdom2.*;
    import org.jdom2.input.SAXBuilder;
    import java.util.List;

public class JDOMExample {
public static void main(String[] args) throws Exception {
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(“data.xml”);
Element root = doc.getRootElement();
List books = root.getChildren(“book”);

    for (Element book : books) {
        String title = book.getChildText("title");
        System.out.println("书名: " + title);
    }
}

---
#### **五、DOM4J解析(高性能库)**
**步骤:**
1. 添加Maven依赖:
   ```xml
   <dependency>
     <groupId>org.dom4j</groupId>
     <artifactId>dom4j</artifactId>
     <version>2.1.4</version>
   </dependency>
  1. 代码实现:
    import org.dom4j.*;
    import org.dom4j.io.SAXReader;
    import java.util.List;

public class DOM4JExample {
public static void main(String[] args) throws Exception {
SAXReader reader = new SAXReader();
Document doc = reader.read(“data.xml”);
Element root = doc.getRootElement();

    List<Node> nodes = root.selectNodes("//book/title");
    for (Node node : nodes) {
        System.out.println("书名: " + node.getText());
    }
}

---
#### **六、StAX解析(流式高效方案)**
```java
import javax.xml.stream.*;
import java.io.FileReader;
public class StAXExample {
    public static void main(String[] args) throws Exception {
        XMLInputFactory factory = XMLInputFactory.newInstance();
        XMLStreamReader reader = factory.createXMLStreamReader(
            new FileReader("data.xml")
        );
        while (reader.hasNext()) {
            int event = reader.next();
            if (event == XMLStreamConstants.START_ELEMENT 
                && reader.getLocalName().equals("title")) {
                System.out.println("书名: " + reader.getElementText());
            }
        }
        reader.close();
    }
}

方法对比与选型建议

方法 内存占用 速度 易用性 适用场景
DOM 中等 小型XML/需修改结构
SAX 极低 大型XML/只读操作
JDOM 中等 中等 需要简洁API的项目
DOM4J 中等 高性能需求/复杂XPath
StAX 极快 流式处理/超大文件

安全提示:所有解析器均应关闭外部实体(XXE防护):

factory.setFeature("http://xml.org/sax/features/external-general-entities", false);

最佳实践总结

  1. 小型配置:优先使用DOM或JDOM,代码简洁
  2. 日志/大数据:选择SAX或StAX避免内存溢出
  3. 现代项目:推荐DOM4J(平衡性能与功能)
  4. 安全第一:始终禁用DTD和外部实体
  5. 异常处理:捕获ParserConfigurationExceptionSAXExceptionIOException
<!-- 示例XML结构(data.xml) -->
<library>
  <book>Java核心技术</title>
    <author>Cay S. Horstmann</author>
  </book>
  <book>Effective Java</title>
    <author>Joshua Bloch</author>
  </book>
</library>

引用说明:

  • Oracle官方文档:Java XML APIs
  • DOM4J官网:dom4j
  • OWASP XXE防护指南:XXE Prevention
  • JDOM官方指南:jdom.org
0