1. 程式人生 > >Java中對xml檔案的四種解析方式

Java中對xml檔案的四種解析方式

books.xml
<?xml version="1.0" encoding="utf-8"?>
<bookstore>
    <book id="1">
        <name>冰與火之歌</name>
        <author>喬治馬丁</author>
        <year>2014</year>
        <price>88</price>
    </book>
    <book id="2">
        <name>安徒生童話</name>
        <year>2004</year>
        <price>83</price>
        <language>English</language>
    </book>
</bookstore>

DOM解析

import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class Dom {

	public static void main(String[] args) {
		try {
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			// 建立DocumentBuilder物件
			DocumentBuilder db = dbf.newDocumentBuilder();
			// 通過DocumentBuilder物件的parse方法載入books.xml檔案到當前目錄下
			Document document = db.parse("books.xml");
			// 獲取所有book節點的集合
			NodeList bookList = document.getElementsByTagName("book");
			// 通過nodeList的getLength()可以獲取bookList的長度
			System.out.println("一共有" + bookList.getLength() + "本書");
			// 遍歷每一個book節點 
			for(int i=0; i<bookList.getLength(); i++) {
				System.out.println("==============開始遍歷第" + (i + 1) + "本書的內容================");
				// 通過item(i)方法獲取一個book節點,nodeList的索引值從0開始 
				Node book = bookList.item(i);
				// 獲取book節點的所有屬性集合
				NamedNodeMap attrs = book.getAttributes();
				System.out.println("第" + (i + 1) + "本書一共有" + attrs.getLength() + "個屬性");
				// 遍歷book的屬性
				for(int j=0; j<attrs.getLength(); j++) {
					// 通過item()方法獲取book節點的某一個屬性
					Node attr = attrs.item(j);
					// 獲取屬性名
					System.out.print("屬性名:" + attr.getNodeName());
					// 獲取屬性值
					System.out.println("--屬性值:" + attr.getNodeValue());
				}
//				// 前提:已經知道book節點有且只能有1個屬性
//				// 將book節點進行強制型別轉換,轉換成Element型別
//				Element book = (Element) bookList.item(i);
//				// 通過getAttribute()方法獲取屬性值
//				String attrValue = book.getAttribute("id");
//				System.out.println("id屬性的屬性值為" + attrValue);
				// 解析book節點的子節點
				NodeList childNodes = book.getChildNodes();
				// <>之間的空白也算是一個子節點(是text型別的子節點),所以會輸出有9個子節點
				System.out.println("第" + (i + 1) + "本書一共有" + childNodes.getLength() + "個子節點");
				// 遍歷childNodes獲取每個節點的節點名和節點值
				for(int k=0; k<childNodes.getLength(); k++) {
					// 區分出text型別的node以及element型別的node
					if(childNodes.item(k).getNodeType() == Node.ELEMENT_NODE) {
						// 獲取element型別節點的節點名
						System.out.print("第" + (k+ 1) + "個節點的節點名:" + childNodes.item(k).getNodeName());
						// 獲取element型別節點的節點值
						// 將會返回null 因為element型別節點的節點值算是該節點的子節點
//						System.out.println(childNodes.item(k).getNodeValue());
						System.out.println("--節點值是:" + childNodes.item(k).getFirstChild().getNodeValue());
						// 得到該子節點中的所有文字資訊(該子節點可能包含子節點)
						// 比如<name><a>aa</a>冰與火之歌</name>將會輸出“aa冰與火之歌”
//						System.out.println("--節點值是:" + childNodes.item(k).getTextContent());
					}
				}
				System.out.println("==============結束遍歷第" + (i + 1) + "本書的內容================");
			}
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
SAX解析
book.java
public class Book {
	private int id;
	private String name;
	private String author;
	private String year;
	private String price;
	private String language;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public String getAuthor() {
		return author;
	}
	public void setAuthor(String author) {
		this.author = author;
	}
	
	public String getYear() {
		return year;
	}
	public void setYear(String year) {
		this.year = year;
	}
	
	public String getPrice() {
		return price;
	}
	public void setPrice(String price) {
		this.price = price;
	}
	
	public String getLanguage() {
		return language;
	}
	public void setLanguage(String language) {
		this.language = language;
	}
}
SAXHandler.java
public class SAXHandler extends DefaultHandler {
	private int index;
	private Book book;
	private List<Book> bookList = new ArrayList<>();
	private String value;
	
	public List<Book> getBookList() {
		return bookList;
	}

	@Override
	public void startDocument() throws SAXException {
		// TODO Auto-generated method stub
		super.startDocument();
		System.out.println("=============開始解析文件==================");
	}
	
	@Override
	public void endDocument() throws SAXException {
		// TODO Auto-generated method stub
		super.endDocument();
		System.out.println("=============結束解析文件==================");
	}
	
	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		// TODO Auto-generated method stub
		super.startElement(uri, localName, qName, attributes);
		if(qName.equals("book")) {
		    book = new Book();
			index++;
			System.out.println("=============開始解析第" + (index) + "本書==================");
			int id = Integer.valueOf(attributes.getValue("id"));
			book.setId(id);
		}
	}
	
	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {
		// TODO Auto-generated method stub
		super.endElement(uri, localName, qName);
		if(qName.equals("name")) {
			book.setName(value);
		} else if(qName.equals("author")) {
			book.setAuthor(value);
		} else if(qName.equals("year")) {
			book.setYear(value);
		} else if(qName.equals("price")) {
			book.setPrice(value);
		} else if(qName.equals("language")) {
			book.setLanguage(value);
		}  else if(qName.equals("book")) {
			bookList.add(book);
			book = null;
			System.out.println("=============結束解析第" + (index) + "本書==================");
		}
	}
	
	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		// TODO Auto-generated method stub
		super.characters(ch, start, length);
		value = new String(ch, start, length);
	}
}
SAX.java
public class SAX {

	public static void main(String[] args) {
		try {
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser parser = factory.newSAXParser();
			SAXHandler handler = new SAXHandler();
			parser.parse("books.xml", handler);
			List<Book> bookList = handler.getBookList();
			for(Book book : bookList) {
				System.out.println(book.getId());
				System.out.println(book.getName());
				System.out.println(book.getAuthor());
				System.out.println(book.getYear());
				System.out.println(book.getPrice());
				System.out.println(book.getLanguage());
				System.out.println("===finish=====");
			}
		} catch (ParserConfigurationException | SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
JDOM解析(導jar包)
public class JDOM {
	public static void main(String[] args) {
		List<Book> bookEntityList = new ArrayList<>();
		Book bookEntity = null;
		try {
			// 建立SAXBuilder物件
			SAXBuilder saxBuilder = new SAXBuilder();
		    // 2.建立一個輸入流,將xml檔案載入到輸入流中
			InputStream in = new FileInputStream("books.xml");
			// 3.通過saxBuilder的build方法,將輸入流載入到saxBuilder中
			Document document = saxBuilder.build(in);
			// 4.通過document物件獲取xml檔案的根節點
			Element rootElement = document.getRootElement();
			// 5.獲取根節點下的子節點的List集合
			List<Element> bookList = rootElement.getChildren();
			for(Element book : bookList) {
				bookEntity = new Book();
				System.out.println("===========開始解析第" + (bookList.indexOf(book) + 1) + "本書============");
				// 解析book的屬性集合
				List<Attribute> attrList = book.getAttributes();
				for(Attribute attr : attrList) {
					String attrName = attr.getName();
					String attrValue = attr.getValue();
					System.out.println("屬性名:" + attrName + "----屬性值:" + attrValue);
					if(attrName.equals("id")) {
						bookEntity.setId(Integer.valueOf(attrValue));
					}
				}
//				String attrValue = book.getAttributeValue("id");
//				System.out.println("屬性名:id" + "----屬性值:" + attrValue);
				List<Element> bookChildren = book.getChildren();
				for(Element bookChild : bookChildren) {
					String nodeName = bookChild.getName();
					String nodeValue = bookChild.getValue();
					System.out.println("節點名:" + nodeName + "----節點值:" + nodeValue);
					if(nodeName.equals("name")) {
						bookEntity.setName(nodeValue);
					} else if(nodeName.equals("author")) {
						bookEntity.setAuthor(nodeValue);
					} else if(nodeName.equals("year")) {
						bookEntity.setYear(nodeValue);
					} else if(nodeName.equals("price")) {
						bookEntity.setPrice(nodeValue);
					} else if(nodeName.equals("language")) {
						bookEntity.setLanguage(nodeValue);
					}
				}
				System.out.println("===========結束解析第" + (bookList.indexOf(book) + 1) + "本書============");
				bookEntityList.add(bookEntity);
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JDOMException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(bookEntityList);
	}
}
book.java同上
DOM4J解析(導jar包)
public class DOM4J {

	public static void main(String[] args) {
		int index = 0;
		// 建立SAXReader物件
		SAXReader saxReader = new SAXReader();
		try {
			// 通過saxReader的read方法載入books.xml物件
			Document document = saxReader.read(new File("books.xml"));
			// 獲取根節點
			Element bookStore =  document.getRootElement();
			// 獲取迭代器
			Iterator<Element> it = bookStore.elementIterator();
			while(it.hasNext()) {
				index++;
				System.out.println("===========開始解析第" + index + "本書=================");
				Element book = it.next();
				List<Attribute> attrList = book.attributes();
				for(Attribute attr : attrList) {
					String name = attr.getName();
					String value = attr.getValue();
					System.out.println("屬性名:" + name + "--屬性值:" + value);
				}
				Iterator<Element> it2 = book.elementIterator();
				while(it2.hasNext()) {
					Element node = it2.next();
					String name = node.getName();
					String value = node.getStringValue();
					System.out.println("節點名:" + name + "--節點值:" + value);
				}
				System.out.println("===========結束解析第" + index + "本書=================");
			}
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
4種解析方法的分析
DOM:
平臺無關的官方解析方式,不只在java中適用
優點:  1.形成了樹結構,直觀好理解,程式碼更易編寫
2.解析過程中樹結構保留在記憶體中,方便修改
缺點:  當xml檔案較大時,對記憶體耗費比較大,容易影響解析效能並造成記憶體溢位
SAX:
基於事件驅動的解析方法,平臺無關的官方解析方式,不只在java中適用
優點:  1.採用事件驅動模式,對記憶體耗費比較小
2.適用於只需要處理xml中資料時
缺點:  1.不易編碼
2.很難同時訪問同一個xml中的多處不同資料
JDOM:
在SAX上擴展出來的解析方法,只有java中能夠使用
優點:  1.僅使用具體類而不使用介面
2.API大量使用了Collections類
DOM4J:
在SAX上擴展出來的解析方法,只有java中能夠使用
優點:  1.JDOM的一種智慧分支,它合併了許多超出基本xml文件表示的內容
2.DOM4J使用介面和抽象基本類方法,是一個優秀的Java XML API
關於解析速度:
對於上述的books.xml
解析速度SAX>DOM>DOM4J>JDOM
book.xml檔案小,所以解析速度DOM>DOM4J
DOM4J比起DOM優勢在於能更快解析較複雜的xml檔案,不妨增加books.xml的內容試試看

以上內容總結自慕課網Java基礎路徑之《Java眼中的XML-檔案讀取》
https://github.com/LuJN/DOMTest
https://github.com/LuJN/SAXTest