Java讀取xml文件的五種方式
前言
在編寫(xiě)與 XML 數(shù)據(jù)交互的現(xiàn)代軟件應(yīng)用時(shí),有效地讀取和解析 XML 文件是至關(guān)重要的。XML(可擴(kuò)展標(biāo)記語(yǔ)言)因其靈活性和自我描述性,已成為數(shù)據(jù)存儲(chǔ)和傳輸?shù)囊环N普遍格式。對(duì)于 Java 開(kāi)發(fā)者來(lái)說(shuō),Java 提供了多種工具和庫(kù)來(lái)處理 XML 文件,每種工具都有其獨(dú)特的特點(diǎn)和最適用的場(chǎng)景。
本文旨在探討 Java 中處理 XML 文件的五種主要方法:DOM、SAX、StAX、JAXB 和 JDOM。這些技術(shù)各有優(yōu)勢(shì)和局限,選擇合適的方法可以大大提高開(kāi)發(fā)效率和程序性能。我們將詳細(xì)介紹每種方法的工作原理、典型用途以及如何在 Java 程序中實(shí)現(xiàn)它們。
1、Java 讀取 xml 文件的五種方式
在 Java 中讀取 XML 文件有多種方法,這里列出五種常見(jiàn)的方式:
- DOM 解析器(Document Object Model):DOM 是處理 XML 文件的一種標(biāo)準(zhǔn)方法,它將整個(gè) XML 文件加載到內(nèi)存中,然后構(gòu)造成一個(gè)樹(shù)狀結(jié)構(gòu)以便程序可以操作。這種方法適合于需要對(duì)文檔進(jìn)行頻繁讀寫(xiě)操作的情況;
- SAX 解析器(Simple API for XML):SAX 是一種基于事件的解析方式,它不會(huì)將整個(gè) XML 文檔加載到內(nèi)存中。這種方法適用于只需要讀取 XML 文檔的情況,特別是處理非常大的文件時(shí);
- StAX 解析器(Streaming API for XML):StAX 是一種拉式解析(Pull Parsing)技術(shù),允許程序員按需讀取 XML 數(shù)據(jù)。這種方式適合于需要對(duì) XML 文檔進(jìn)行增量處理的情況;
- JAXB(Java Architecture for XML Binding):JAXB 允許 Java 開(kāi)發(fā)者通過(guò)注解將 Java 對(duì)象映射到 XML 文件,反之亦然。這適用于需要將 XML 數(shù)據(jù)直接轉(zhuǎn)換為 Java 對(duì)象的場(chǎng)合;
- JDOM(Java Document Object Model):JDOM 提供了一種簡(jiǎn)潔而易用的 API,用于解析、創(chuàng)建和操作 XML 文檔。它基于樹(shù)形結(jié)構(gòu),類(lèi)似于 DOM,但提供了更簡(jiǎn)單的 API,適用于中小型 XML 文件的處理。
首先是 XML 示例:
xml
復(fù)制代碼
<?xml version="1.0" encoding="UTF-8"?>
<library>
<book>
<title>Java Programming</title>
<author>John Smith</author>
<year>2022</year>
</book>
<book>
<title>Python Basics</title>
<author>Jane Doe</author>
<year>2021</year>
</book>
</library>
接下來(lái),我們將使用不同的方式讀取并打印這個(gè) XML 示例。
2、DOM(文檔對(duì)象模型)解析
DOM 將整個(gè) XML 文檔加載到內(nèi)存中,以樹(shù)形結(jié)構(gòu)表示。這種方式易于遍歷和操作,適合對(duì)整個(gè)文檔進(jìn)行多次讀寫(xiě)操作,但可能消耗大量?jī)?nèi)存,不適合處理大型 XML 文件。
DOM 是 Java 標(biāo)準(zhǔn)庫(kù)的一部分,無(wú)需額外引入依賴(lài)。
代碼實(shí)現(xiàn):
package com.lizhengi;
import org.w3c.dom.*;
import javax.xml.parsers.*;
/**
* DOM 方式讀取 XML文件
* @author lizhengi
*/
public class DomReadExample {
public static void main(String[] args) throws Exception {
// 創(chuàng)建一個(gè) DocumentBuilderFactory 實(shí)例,用于創(chuàng)建 DocumentBuilder
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 使用工廠創(chuàng)建一個(gè) DocumentBuilder 實(shí)例,用于解析 XML 文檔
DocumentBuilder builder = factory.newDocumentBuilder();
// 使用 ClassLoader 獲取資源文件的輸入流,并解析成 Document 對(duì)象
Document document = builder.parse(DomReadExample.class.getClassLoader().getResourceAsStream("example.xml"));
// 獲取 XML 文檔中所有名為 "book" 的元素節(jié)點(diǎn)
NodeList bookNodes = document.getElementsByTagName("book");
// 遍歷每個(gè) "book" 元素節(jié)點(diǎn),并輸出其子元素的內(nèi)容
for (int i = 0; i < bookNodes.getLength(); i++) {
Node bookNode = bookNodes.item(i);
Element bookElement = (Element) bookNode;
// 獲取 "title"、"author" 和 "year" 子元素的內(nèi)容
String title = bookElement.getElementsByTagName("title").item(0).getTextContent();
String author = bookElement.getElementsByTagName("author").item(0).getTextContent();
String year = bookElement.getElementsByTagName("year").item(0).getTextContent();
// 打印輸出圖書(shū)的信息
System.out.println("Title: " + title + ", Author: " + author + ", Year: " + year);
}
}
}
3、SAX(簡(jiǎn)單 API for XML)解析
SAX 以事件驅(qū)動(dòng)的方式逐行解析 XML 文檔,并在解析過(guò)程中觸發(fā)事件。它不需要將整個(gè)文檔加載到內(nèi)存中,因此適用于處理大型 XML 文件,但相對(duì)于 DOM,它的操作稍顯復(fù)雜。
SAX 是 Java 標(biāo)準(zhǔn)庫(kù)的一部分,無(wú)需額外引入依賴(lài)。
代碼實(shí)現(xiàn):
package com.lizhengi;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
/**
* SAX 解析 XML 示例
* 該類(lèi)繼承了 DefaultHandler 類(lèi),用于處理 SAX 事件
*
* @author liziheng
*/
public class SaxReadExample extends DefaultHandler {
// 表示是否在書(shū)籍元素內(nèi)部
private boolean inBookElement = false;
// 用于存儲(chǔ)當(dāng)前正在處理的元素的名稱(chēng)
private String currentElement;
// 當(dāng)前書(shū)籍的標(biāo)題
private String currentTitle;
// 當(dāng)前書(shū)籍的作者
private String currentAuthor;
// 當(dāng)前書(shū)籍的年份
private String currentYear;
/**
* 開(kāi)始解析元素時(shí)調(diào)用
*
* @param uri 元素的命名空間 URI
* @param localName 元素的本地名稱(chēng)
* @param qName 元素的限定名稱(chēng)
* @param attributes 元素的屬性
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
if ("book".equals(qName)) {
// 進(jìn)入書(shū)籍元素內(nèi)部
inBookElement = true;
}
// 存儲(chǔ)當(dāng)前元素的名稱(chēng)
currentElement = qName;
}
/**
* 處理元素字符數(shù)據(jù)時(shí)調(diào)用
*
* @param ch 字符數(shù)組
* @param start 字符數(shù)據(jù)的起始索引
* @param length 字符數(shù)據(jù)的長(zhǎng)度
*/
@Override
public void characters(char[] ch, int start, int length) {
if (inBookElement) {
String content = new String(ch, start, length).trim();
if (!content.isEmpty()) {
if ("title".equals(currentElement)) {
// 設(shè)置當(dāng)前書(shū)籍的標(biāo)題
currentTitle = content;
} else if ("author".equals(currentElement)) {
// 設(shè)置當(dāng)前書(shū)籍的作者
currentAuthor = content;
} else if ("year".equals(currentElement)) {
// 設(shè)置當(dāng)前書(shū)籍的年份
currentYear = content;
}
}
}
}
/**
* 結(jié)束解析元素時(shí)調(diào)用
*
* @param uri 元素的命名空間 URI
* @param localName 元素的本地名稱(chēng)
* @param qName 元素的限定名稱(chēng)
*/
@Override
public void endElement(String uri, String localName, String qName) {
if ("book".equals(qName)) {
// 打印當(dāng)前書(shū)籍的信息
System.out.println("Title: " + currentTitle + ", Author: " + currentAuthor + ", Year: " + currentYear);
// 重置當(dāng)前書(shū)籍的信息
currentTitle = null;
currentAuthor = null;
currentYear = null;
// 退出書(shū)籍元素內(nèi)部
inBookElement = false;
}
}
/**
* 主方法,程序入口
*
* @param args 命令行參數(shù)
* @throws Exception 拋出異常
*/
public static void main(String[] args) throws Exception {
// 創(chuàng)建 XML 解析器
XMLReader reader = XMLReaderFactory.createXMLReader();
// 設(shè)置內(nèi)容處理器為當(dāng)前類(lèi)的實(shí)例
reader.setContentHandler(new SaxReadExample());
// 解析 XML 文件并觸發(fā) SAX 事件
reader.parse(new InputSource(SaxReadExample.class.getClassLoader().getResourceAsStream("example.xml")));
}
}
4、StAX(流 API for XML)解析
StAX 提供了類(lèi)似于 SAX 的事件驅(qū)動(dòng)的解析方式,但與 SAX 不同,它提供了更簡(jiǎn)潔的 API,并允許開(kāi)發(fā)者在解析過(guò)程中靈活地控制流。這使得 StAX 更容易使用和理解。
引入依賴(lài):
<dependency>
<groupId>javax.xml.stream</groupId>
<artifactId>stax-api</artifactId>
<version>1.0-2</version>
</dependency>
代碼實(shí)現(xiàn):
package com.lizhengi;
import javax.xml.stream.*;
/**
* 使用 StAX(Streaming API for XML)方式讀取 XML 文件示例
* 該類(lèi)實(shí)現(xiàn)了對(duì) XML 文件的解析,并打印每本書(shū)的信息
*
* @author lizhengi
*/
public class StaxReadExample {
public static void main(String[] args) throws Exception {
// 創(chuàng)建 XMLInputFactory 實(shí)例,用于創(chuàng)建 XMLStreamReader
XMLInputFactory factory = XMLInputFactory.newInstance();
// 創(chuàng)建 XMLStreamReader 實(shí)例,用于逐行讀取 XML 文件內(nèi)容
XMLStreamReader reader = factory.createXMLStreamReader(StaxReadExample.class.getClassLoader().getResourceAsStream("example.xml"));
// 用于存儲(chǔ)當(dāng)前正在處理的元素的名稱(chēng)和內(nèi)容
String currentElement = null;
String currentTitle = null;
String currentAuthor = null;
String currentYear = null;
// 循環(huán)讀取 XML 文件中的內(nèi)容
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_ELEMENT:
// 開(kāi)始處理元素時(shí),記錄當(dāng)前元素的名稱(chēng)
currentElement = reader.getLocalName();
break;
case XMLStreamConstants.CHARACTERS:
// 處理元素的字符數(shù)據(jù)時(shí),獲取字符數(shù)據(jù)的內(nèi)容
String content = reader.getText().trim();
if (!content.isEmpty()) {
// 根據(jù)當(dāng)前元素的名稱(chēng),存儲(chǔ)相應(yīng)的內(nèi)容
if ("title".equals(currentElement)) {
currentTitle = content;
} else if ("author".equals(currentElement)) {
currentAuthor = content;
} else if ("year".equals(currentElement)) {
currentYear = content;
}
}
break;
case XMLStreamConstants.END_ELEMENT:
// 結(jié)束處理元素時(shí),檢查是否為書(shū)籍元素的結(jié)束標(biāo)簽
if ("book".equals(reader.getLocalName())) {
// 打印當(dāng)前書(shū)籍的信息
System.out.println("Title: " + currentTitle + ", Author: " + currentAuthor + ", Year: " + currentYear);
// 重置當(dāng)前書(shū)籍的信息,準(zhǔn)備處理下一本書(shū)
currentTitle = null;
currentAuthor = null;
currentYear = null;
}
break;
}
}
}
}
5、JAXB(Java Architecture for XML Binding)
JAXB 允許將 XML 數(shù)據(jù)綁定到 Java 對(duì)象,從而簡(jiǎn)化了 XML 數(shù)據(jù)與 Java 對(duì)象之間的轉(zhuǎn)換過(guò)程。它通常用于處理 XML 數(shù)據(jù)的映射和序列化,而不是直接解析整個(gè) XML 文檔。
JAXB 也是 Java 標(biāo)準(zhǔn)庫(kù)的一部分,無(wú)需額外引入依賴(lài)。
代碼實(shí)現(xiàn):
package com.lizhengi;
import javax.xml.bind.*;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;
/**
* XML 文件對(duì)應(yīng)的 Java 類(lèi),根元素為 "library"
*/
@XmlRootElement(name = "library")
class Library {
// 用于存儲(chǔ)書(shū)籍信息的列表,每個(gè)元素對(duì)應(yīng)一個(gè)書(shū)籍
@XmlElement(name = "book")
public List<Book> books = new ArrayList<Book>();
}
/**
* 書(shū)籍信息的 Java 類(lèi)
*/
class Book {
// 書(shū)籍標(biāo)題
@XmlElement
public String title;
// 書(shū)籍作者
@XmlElement
public String author;
// 出版年份
@XmlElement
public int year;
}
/**
* 使用 JAXB 方式讀取 XML 文件
* @author lizhengi
*/
public class JaxbReadExample {
public static void main(String[] args) throws Exception {
// 創(chuàng)建 JAXBContext 實(shí)例,用于創(chuàng)建 Unmarshaller
JAXBContext context = JAXBContext.newInstance(Library.class);
// 創(chuàng)建 Unmarshaller 實(shí)例,用于將 XML 數(shù)據(jù)轉(zhuǎn)換為 Java 對(duì)象
Unmarshaller unmarshaller = context.createUnmarshaller();
// 使用 Unmarshaller 解析 XML 文件,并將其轉(zhuǎn)換為 Library 對(duì)象
Library library = (Library) unmarshaller.unmarshal(JaxbReadExample.class.getClassLoader().getResourceAsStream("example.xml"));
// 遍歷 Library 中的每本書(shū),并打印其信息
for (Book book : library.books) {
System.out.println("Title: " + book.title + ", Author: " + book.author + ", Year: " + book.year);
}
}
}
6、JDOM(Java Document Object Model)
JDOM 提供了一種簡(jiǎn)潔而易用的 API,用于解析、創(chuàng)建和操作 XML 文檔。它基于樹(shù)形結(jié)構(gòu),類(lèi)似于 DOM,但提供了更簡(jiǎn)單的 API,適用于中小型 XML 文件的處理。
引入依賴(lài):
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom2</artifactId>
<version>2.0.6.1</version>
</dependency>
代碼實(shí)現(xiàn):
package com.lizhengi;
import org.jdom2.*;
import org.jdom2.input.*;
/**
* 使用 JDOM 方式讀取 XML 文件
* 該程序從 XML 文件中讀取圖書(shū)信息,并打印每本書(shū)的標(biāo)題、作者和年份
* XML 文件的根元素為 "library",每個(gè) "book" 元素表示一本書(shū)
* @author lizhengi
*/
public class JdomReadExample {
public static void main(String[] args) throws Exception {
// 使用 SAXBuilder 創(chuàng)建解析器
SAXBuilder builder = new SAXBuilder();
// 使用解析器構(gòu)建 XML 文檔對(duì)象
Document document = builder.build(JdomReadExample.class.getClassLoader().getResourceAsStream("example.xml"));
// 獲取 XML 文檔的根元素
Element root = document.getRootElement();
// 遍歷根元素下的所有 "book" 元素,并輸出每本書(shū)的信息
for (Element book : root.getChildren("book")) {
// 獲取書(shū)籍的標(biāo)題、作者和年份
String title = book.getChildText("title");
String author = book.getChildText("author");
String year = book.getChildText("year");
// 打印輸出書(shū)籍信息
System.out.println("Title: " + title + ", Author: " + author + ", Year: " + year);
}
}
}
以上就是Java讀取xml文件的五種方式的詳細(xì)內(nèi)容,更多關(guān)于Java讀取xml文件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java遞歸實(shí)現(xiàn)評(píng)論多級(jí)回復(fù)功能
這篇文章主要介紹了Java遞歸實(shí)現(xiàn)評(píng)論多級(jí)回復(fù)功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06
Mybatis Plus 代碼生成器的實(shí)現(xiàn)
這篇文章主要介紹了Mybatis Plus 代碼生成器的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Java調(diào)用python代碼的五種方式總結(jié)
這篇文章主要給大家介紹了關(guān)于Java調(diào)用python代碼的五種方式,在Java中調(diào)用Python函數(shù)的方法有很多種,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09
springboot?vue接口測(cè)試HutoolUtil?TreeUtil處理樹(shù)形結(jié)構(gòu)
這篇文章主要介紹了springboot?vue接口測(cè)試HutoolUtil?TreeUtil處理樹(shù)形結(jié)構(gòu),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
微信小程序完整項(xiàng)目實(shí)戰(zhàn)記錄(前端+SpringBoot后端)
隨著微信小程序的流行,越來(lái)越多的開(kāi)發(fā)者開(kāi)始涉足小程序開(kāi)發(fā),下面這篇文章主要給大家介紹了關(guān)于微信小程序完整項(xiàng)目實(shí)戰(zhàn)的相關(guān)資料,項(xiàng)目包括前端+SpringBoot后端,需要的朋友可以參考下2024-09-09
深入淺析drools中Fact的equality?modes
這篇文章主要介紹了drools中Fact的equality?modes的相關(guān)知識(shí),本文通過(guò)圖文實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05

