Java中對xml檔案的四種解析方式
阿新 • • 發佈:2019-02-16
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