首先建立一個xml文檔,文檔内容如下
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book id="1">
<name>程式設計之美</name>
<price>34.0</price>
<author>《程式設計之美》小組</author>
</book>
<book id="2">
<name>平凡的世界</name>
<price>56.0</price>
<author>路遙</author>
<language>中文</language>
</book>
</bookstore>
因為xml定義是書店的書本詳情,解析完xml之後,希望把解析之後的資料儲存下來,是以定義了一個Book的Entity,定義好各個屬性
package com.ikok.parsexml;
public class Book {
private String id;
private String name;
private String price;
private String author;
private String language;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
}
DOM解析:
package com.ikok.parsexml;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
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 domXml {
private static List<Book> booksList = new ArrayList<Book>();
public static void main(String[] args) {
// 建立一個DocumentBuilderFactory對象
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
// 建立一個DocumentBuilder對象
DocumentBuilder db = dbf.newDocumentBuilder();
// 通過DocumentBuilder對象的parse方法加載xml檔案到目前項目
Document document = db.parse("books.xml");
// 擷取所有book節點的集合
NodeList bookList = document.getElementsByTagName("book");
// 周遊每一個book節點,通過bookList.getLength()方法知道集合的長度
System.out.println("一共有 " + bookList.getLength() + " 本書");
for (int i = 0; i < bookList.getLength(); i++) {
Book bookItem = new Book();
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(i)的方法擷取一個book節點的某個屬性
Node attr = attrs.item(j);
// 擷取屬性名
System.out.print("屬性名為:" + attr.getNodeName());
// 擷取屬性值
System.out.println("----屬性值為:" + attr.getNodeValue());
if(attr.getNodeName().equals("id")){
bookItem.setId(attr.getNodeValue());
}
}
// 當知道節點有且隻有一個屬性時,進行強制類型轉換,通過getAttribute()方法擷取屬性值
// Element book = (Element) bookList.item(i);
// String attrValue = book.getAttribute("id");
// System.out.println("id :" + attrValue);
//解析book節點的子節點
NodeList childList = book.getChildNodes();
System.out.println("第 " + (i+1) + " 本書共有 " + childList.getLength() + " 個子節點");
for (int k = 0; k < childList.getLength(); k++) {
// 區分出text類型的node以及element類型node
if (childList.item(k).getNodeType() == Node.ELEMENT_NODE) {
// 擷取了element類型節點的節點名
System.out.print("第 " + (i+1) + " 本書的子節點名: " + childList.item(k).getNodeName() + "----");
// 如果目前節點中還有節點,則屬性值為空。比如<name><a>aa</a><b>bb</b>第一行代碼</name>
System.out.println(" 屬性值: " + childList.item(k).getFirstChild().getNodeValue());
// 這樣會輸出所有子節點和節點之間的内容。會輸出 aabb第一行代碼
// System.out.println(childList.item(k).getTextContent());
if(childList.item(k).getNodeName().equals("name")){
bookItem.setName(childList.item(k).getFirstChild().getNodeValue());
} else if(childList.item(k).getNodeName().equals("price")){
bookItem.setPrice(childList.item(k).getFirstChild().getNodeValue());
} else if(childList.item(k).getNodeName().equals("author")){
bookItem.setAuthor(childList.item(k).getFirstChild().getNodeValue());
} else if(childList.item(k).getNodeName().equals("language")){
bookItem.setLanguage(childList.item(k).getFirstChild().getNodeValue());
}
}
}
System.out.println("-----------結束周遊第" + (i+1) + "本書的内容-----------");
System.out.println();
booksList.add(bookItem);
bookItem = null;
}
for (Book item : booksList) {
System.out.println("書本id :" + item.getId());
System.out.println("書本名字 :" + item.getName());
System.out.println("書本價格 :" + item.getPrice());
System.out.println("書本作者 :" + item.getAuthor());
System.out.println("書本語言 :" + item.getLanguage());
System.out.println("---------------------------------");
}
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
結果:
一共有 2 本書
-----------開始周遊第1本書的内容-----------
第 1 本書共有 1 個屬性
屬性名為:id----屬性值為:1
第 1 本書共有 7 個子節點
第 1 本書的子節點名: name---- 屬性值: 程式設計之美
第 1 本書的子節點名: price---- 屬性值: 34.0
第 1 本書的子節點名: author---- 屬性值: 《程式設計之美》小組
-----------結束周遊第1本書的内容-----------
-----------開始周遊第2本書的内容-----------
第 2 本書共有 1 個屬性
屬性名為:id----屬性值為:2
第 2 本書共有 9 個子節點
第 2 本書的子節點名: name---- 屬性值: 平凡的世界
第 2 本書的子節點名: price---- 屬性值: 56.0
第 2 本書的子節點名: author---- 屬性值: 路遙
第 2 本書的子節點名: language---- 屬性值: 中文
-----------結束周遊第2本書的内容-----------
書本id :1
書本名字 :程式設計之美
書本價格 :34.0
書本作者 :《程式設計之美》小組
書本語言 :null
---------------------------------
書本id :2
書本名字 :平凡的世界
書本價格 :56.0
書本作者 :路遙
書本語言 :中文
---------------------------------
SAX解析:
package com.ikok.parsexml;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
public class SAXXml {
public static void main(String[] args) {
// 建立一個SAXParserFactory的執行個體
SAXParserFactory saxpf = SAXParserFactory.newInstance();
try {
// 通過SAXParserFactory的執行個體擷取SAXParser的執行個體
SAXParser parser = saxpf.newSAXParser();
SAXParserHandler handler = new SAXParserHandler();
parser.parse("books.xml", handler);
System.out.println("共有 " + handler.getBookList().size() + " 本書");
for (Book book : handler.getBookList()) {
System.out.println("書本id :" + book.getId());
System.out.println("書本名字 :" + book.getName());
System.out.println("書本價格 :" + book.getPrice());
System.out.println("書本作者 :" + book.getAuthor());
System.out.println("書本語言 :" + book.getLanguage());
System.out.println("---------------------------------");
}
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
因為SAX解析xml的解析方法需要一個DefaultHandler參數,是以我定義了一個SAXParserHandler來繼承這個類,重寫部分方法
package com.ikok.parsexml;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class SAXParserHandler extends DefaultHandler {
// 書本的序号
int bookIndex = 0;
/**
* 某個屬性值
* 因為屬性名在startElement()方法中得到,而屬性值卻在characters()方法中得到
* 為了能把屬性名和屬性值加到book執行個體中去,在endElement()方法前,另外兩個方法都執行了,是以在這進行處理
*/
String value = null;
Book book = null;
private List<Book> bookList = new ArrayList<Book>();
public List<Book> getBookList() {
return bookList;
}
// 用來周遊xml檔案的開始标簽
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
// 開始解析book元素的屬性
if(qName.equals("book")){
// 建立一個book對象
book = new Book();
bookIndex++;
System.out.println("-----------開始周遊第" + bookIndex + "本書的内容-----------");
// // 已知book元素下屬性的名稱,根據屬性名擷取屬性值
// String value = attributes.getValue("id");
// System.out.println("id:" + value);
// 不知道book元素下屬性的名稱以及個數,擷取屬性名及屬性值
// 屬性個數
int num = attributes.getLength();
for (int i = 0; i < num; i++) {
System.out.print("第 " + (i+1) + "個屬性名: " + attributes.getQName(i));
System.out.println(" 屬性值: " + attributes.getValue(i));
if (attributes.getQName(i).equals("id")) {
book.setId(attributes.getValue(i));
}
}
} else if(!qName.equals("book") && !qName.equals("bookstore")){
System.out.print("節點名:" + qName + " 節點值:");
}
};
// 用來周遊xml檔案的結束标簽
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
// 針對一本書的内容是否周遊結束
if (qName.equals("book")) {
// 清空book,友善執行下一個
bookList.add(book);
book = null;
System.out.println("-----------結束周遊第" + bookIndex + "本書的内容-----------");
} else if(qName.equals("name")){
book.setName(value);
} else if(qName.equals("price")){
book.setPrice(value);
} else if(qName.equals("author")){
book.setAuthor(value);
} else if(qName.equals("language")){
book.setLanguage(value);
}
};
// 用來标志解析開始
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
super.startDocument();
System.out.println("SAX解析開始");
}
// 用來标志解析結束
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
System.out.println("SAX解析結束");
}
@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);
// 預設情況下,會把xml中的換行符也算進去,輸出格式不正确,去掉換行符
if (!value.trim().equals("")) {
System.out.println(value);
}
}
}
結果:
SAX解析開始
-----------開始周遊第1本書的内容-----------
第 1個屬性名: id 屬性值: 1
節點名:name 節點值:程式設計之美
節點名:price 節點值:34.0
節點名:author 節點值:《程式設計之美》小組
-----------結束周遊第1本書的内容-----------
-----------開始周遊第2本書的内容-----------
第 1個屬性名: id 屬性值: 2
節點名:name 節點值:平凡的世界
節點名:price 節點值:56.0
節點名:author 節點值:路遙
節點名:language 節點值:中文
-----------結束周遊第2本書的内容-----------
SAX解析結束
共有 2 本書
書本id :1
書本名字 :程式設計之美
書本價格 :34.0
書本作者 :《程式設計之美》小組
書本語言 :null
---------------------------------
書本id :2
書本名字 :平凡的世界
書本價格 :56.0
書本作者 :路遙
書本語言 :中文
---------------------------------
JDOM解析:
package com.ikok.parsexml;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
public class JdomXml {
private static List<Book> bookList = new ArrayList<Book>();
public static void main(String[] args) {
// 建立一個SAXBuilder對象
SAXBuilder saxbuilder = new SAXBuilder();
// 建立一個輸入流,将xml加載到輸入流中
InputStream is;
try {
is = new FileInputStream("books.xml");
// 防止解析亂碼,将xml的encoding屬性改為UTF-8,或者在代碼中設定輸入流的編碼方式
// InputStreamReader isr = new InputStreamReader(is, "UTF-8");
// Document document = (Document) saxbuilder.build(isr);
// 通過saxbuilder.build()方法,将輸入流加載到saxbuilder中
Document document = (Document) saxbuilder.build(is);
// 通過document對象擷取xml的根節點
Element rootElement = document.getRootElement();
// 擷取根節點下的子節點的集合
List<Element> elementList = rootElement.getChildren();
for (Element element : elementList) {
Book book = new Book();
System.out.println("---------開始解析第" + (elementList.indexOf(element)+1) + "本書-----------------");
// // 知道屬性的名字及個數
// System.out.println(element.getAttributeValue("id"));
// 擷取屬性集合,不知道屬性的名字及個數
List<Attribute> attrList = element.getAttributes();
for (Attribute attribute : attrList) {
// 屬性名
String attrName = attribute.getName();
// 屬性值
String attrValue = attribute.getValue();
// 存儲到Book中
if (attrName.equals("id")) {
book.setId(attrValue);
}
System.out.println("屬性名:" + attrName + "----屬性值:" + attrValue);
}
// 對book節點下的子節點的節點名以及節點值進行解析
List<Element> childList = element.getChildren();
for (Element child : childList) {
// 屬性名
String attrName = child.getName();
// 屬性值
String attrValue = child.getValue();
// 存儲到Book中
if(attrName.equals("name")){
book.setName(attrValue);
} else if(attrName.equals("price")){
book.setPrice(attrValue);
} else if(attrName.equals("author")){
book.setAuthor(attrValue);
} else if(attrName.equals("language")){
book.setLanguage(attrValue);
}
System.out.println("子節點名:" + attrName + "----子節點屬性值:" + attrValue);
}
System.out.println("---------結束解析第" + (elementList.indexOf(element)+1) + "本書-----------------");
bookList.add(book);
book = null;
}
for (Book item : bookList) {
System.out.println("書本id :" + item.getId());
System.out.println("書本名字 :" + item.getName());
System.out.println("書本價格 :" + item.getPrice());
System.out.println("書本作者 :" + item.getAuthor());
System.out.println("書本語言 :" + item.getLanguage());
System.out.println("---------------------------------");
}
} 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();
}
}
}
結果:
---------開始解析第1本書-----------------
屬性名:id----屬性值:1
子節點名:name----子節點屬性值:程式設計之美
子節點名:price----子節點屬性值:34.0
子節點名:author----子節點屬性值:《程式設計之美》小組
---------結束解析第1本書-----------------
---------開始解析第2本書-----------------
屬性名:id----屬性值:2
子節點名:name----子節點屬性值:平凡的世界
子節點名:price----子節點屬性值:56.0
子節點名:author----子節點屬性值:路遙
子節點名:language----子節點屬性值:中文
---------結束解析第2本書-----------------
書本id :1
書本名字 :程式設計之美
書本價格 :34.0
書本作者 :《程式設計之美》小組
書本語言 :null
---------------------------------
書本id :2
書本名字 :平凡的世界
書本價格 :56.0
書本作者 :路遙
書本語言 :中文
---------------------------------
DOM4J解析:
package com.ikok.parsexml;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class dom4jXml {
private static List<Book> bookList = new ArrayList<Book>();
// 書的序号
static int bookIndex = 0;
public static void main(String[] args) {
// 建立SAXReader的對象
SAXReader reader = new SAXReader();
try {
// 通過reader的read()方法加載xml檔案,擷取document對象
Document document = reader.read(new File("books.xml"));
// 擷取根節點
Element rootElement = document.getRootElement();
// 擷取疊代器
Iterator iterator = rootElement.elementIterator();
// 周遊疊代器,擷取根節點中的資訊
while (iterator.hasNext()) {
bookIndex++;
Book bookItem = new Book();
System.out.println("----------開始周遊第" + bookIndex + "本書------------");
Element book = (Element) iterator.next();
// 擷取屬性名和屬性值
List<Attribute> attrList = book.attributes();
for (Attribute attr : attrList) {
if(attr.getName().equals("id")){
bookItem.setId(attr.getValue());
}
System.out.println("屬性名:" + attr.getName() + "----屬性值:" + attr.getValue());
}
Iterator it = book.elementIterator();
while (it.hasNext()) {
Element element = (Element) it.next();
if(element.getName().equals("name")){
bookItem.setName(element.getStringValue());
} else if(element.getName().equals("price")){
bookItem.setPrice(element.getStringValue());
} else if(element.getName().equals("author")){
bookItem.setAuthor(element.getStringValue());
} else if(element.getName().equals("language")){
bookItem.setLanguage(element.getStringValue());
}
System.out.println("子節點名:" + element.getName() + "----子節點屬性值:" + element.getStringValue());
}
System.out.println("----------結束周遊第" + bookIndex + "本書------------");
bookList.add(bookItem);
bookItem = null;
}
for (Book item : bookList) {
System.out.println("書本id :" + item.getId());
System.out.println("書本名字 :" + item.getName());
System.out.println("書本價格 :" + item.getPrice());
System.out.println("書本作者 :" + item.getAuthor());
System.out.println("書本語言 :" + item.getLanguage());
System.out.println("---------------------------------");
}
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
結果:
----------開始周遊第1本書------------
屬性名:id----屬性值:1
子節點名:name----子節點屬性值:程式設計之美
子節點名:price----子節點屬性值:34.0
子節點名:author----子節點屬性值:《程式設計之美》小組
----------結束周遊第1本書------------
----------開始周遊第2本書------------
屬性名:id----屬性值:2
子節點名:name----子節點屬性值:平凡的世界
子節點名:price----子節點屬性值:56.0
子節點名:author----子節點屬性值:路遙
子節點名:language----子節點屬性值:中文
----------結束周遊第2本書------------
書本id :1
書本名字 :程式設計之美
書本價格 :34.0
書本作者 :《程式設計之美》小組
書本語言 :null
---------------------------------
書本id :2
書本名字 :平凡的世界
書本價格 :56.0
書本作者 :路遙
書本語言 :中文
---------------------------------
這裡,JDOM我用的是2.0.5的包,DOM4J我用的是1.6.1的包。
以目前這個XML為解析的目标的情況下,解析耗時,SAX耗時比DOM短,DOM4J耗時比JDOM短。
目前hibernate架構中也是使用的DOM4J解析XML。