des...
四種解析方式:
DOM
SAX
JDOM
DOM4J
解析目标-books.xml檔案
<?xml version="1.0" encoding="UTF-8" ?>
<books>
<book id="1">
<name>XML深入淺出</name>
<author>Imooc</author>
<year>2014</year>
<price>89</price>
</book>
<book id="2">
<name>Java從入門到精通</name>
<author>Imooc</author>
<price>369</price>
</book>
</books>
1. DOM方式解析
package imooc
import org.junit.Test
import org.xml.sax.SAXException
import java.io.IOException
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.parsers.ParserConfigurationException
import javax.xml.soap.Node
/**
* @author futao
* Created on 2017/11/2 - 18:19.
*/
class XML {
@Test
fun DOM() {
//1.建立一個DocumentBuilderFactory對象
val builderFactory = DocumentBuilderFactory.newInstance()
try {
//2.建立一個DocumentBuilder
val documentBuilder = builderFactory.newDocumentBuilder()
//通過DocumentBuilder對象的parse方法加載books.xml到目前項目下
val parse = documentBuilder.parse("D:\\src\\springhibernate\\springshibernate\\src\\test\\kotlin\\imooc\\books.xml")
//擷取節點(book)的集合
val bookNodeList = parse.getElementsByTagName("book")
println("book節點個數為${bookNodeList.length}")
//周遊每一個book節點
for (i in 0 until bookNodeList.length) {
//周遊每個book節點的所有屬性的集合
val bookNodeAttributes = bookNodeList.item(i).attributes
for (j in 0 until bookNodeAttributes.length) {
println("第${i + 1} 個book節點公有${bookNodeList.item(i).attributes.length}個屬性")
println("屬性:" + bookNodeAttributes.item(j))
println(bookNodeAttributes.item(j).nodeName)
println(bookNodeAttributes.item(j).nodeValue)
//擷取目前book節點的子節點集合
val bookNodeChildNodes = bookNodeList.item(i).childNodes
//會把空格和換行符也當成節點
println("第${i + 1} 本書共有${(bookNodeChildNodes.length - 1) / 2}個子節點")
// for (k in 0 until (bookNodeChildNodes.length - 1) / 2) {
(0 until bookNodeChildNodes.length - 1)
.filter { bookNodeChildNodes.item(it).nodeType == Node.ELEMENT_NODE }
.forEach {
print("子節點" + bookNodeChildNodes.item(it).nodeName)
//null
// println(bookNodeChildNodes.item(it).nodeValue)
println(" 對應的值為 " + bookNodeChildNodes.item(it).firstChild.nodeValue)
// println(" 對應的值為 " + bookNodeChildNodes.item(it).textContent)
}
}
}
} catch (e: ParserConfigurationException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
} catch (e: SAXException) {
e.printStackTrace()
}
}
}
結果
book節點個數為2
第1 個book節點公有1個屬性
屬性:id="1"
id
1
第1 本書共有4個子節點
子節點name 對應的值為 XML深入淺出
子節點author 對應的值為 Imooc
子節點year 對應的值為 2014
子節點price 對應的值為 89
第2 個book節點公有1個屬性
屬性:id="2"
id
2
第2 本書共有3個子節點
子節點name 對應的值為 Java從入門到精通
子節點author 對應的值為 Imooc
子節點price 對應的值為 369
2.SAX方式解析
Book.class
package imooc;
/**
* @author futao
* Created on 2017/11/3 - 11:05.
*/
public class Book {
private int id;
private String name;
private String author;
private String year;
private String price;
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;
}
}
@Test
fun bySAX() {
val sAXParserFactory = SAXParserFactory.newInstance()
val sAXParser = sAXParserFactory.newSAXParser()
//需要編寫處理類MySAXParserHandler
sAXParser.parse("D:\\src\\springhibernate\\springshibernate\\src\\test\\kotlin\\imooc\\books.xml", MySAXParserHandler())
}
class MySAXParserHandler : DefaultHandler() {
//周遊xml的book節點的索引
private var bookIndex = 0
//儲存book對象
private var bookList = ArrayList<Book>()
//目前的book對象
var book = Book()
//目前文本内容
var trim = ""
/**
* 周遊xml的檔案開始标簽
*/
override fun startElement(uri: String?, localName: String?, qName: String?, attributes: Attributes?) {
super.startElement(uri, localName, qName, attributes)
if (qName!! == "book") {
book = Book()
bookList.add(book)
bookIndex++
println("開始周遊第$bookIndex 本書")
// val value = attributes!!.getValue("id")
// println(value)
for (i in 0 until attributes!!.length) {
print("屬性名為:" + attributes.getQName(i))
println("屬性值為:" + attributes.getValue(i))
book.id = attributes.getValue(i).toInt()
}
} else if (qName != "book" && qName != "books") {
print("子節點名字為: $qName 子節點的值為: ")
}
}
/**
* 周遊xml檔案的結束标簽
*/
override fun endElement(uri: String?, localName: String?, qName: String?) {
super.endElement(uri, localName, qName)
when (qName) {
"name" -> book.name = trim
"author" -> book.author = trim
"year" -> book.year = trim
"price" -> book.price = trim
}
if (qName == "book") {
println("========================第$bookIndex 本書周遊完成")
}
}
/**
* 标志解析開始
*/
override fun startDocument() {
super.startDocument()
println("SAX解析開始...")
}
/**
* 标志解析結束
*/
override fun endDocument() {
super.endDocument()
println("SAX解析結束...")
println(GsonBuilder().serializeNulls().setPrettyPrinting().create().toJson(bookList))
}
/**
* 解析内容,擷取文本
*/
override fun characters(ch: CharArray?, start: Int, length: Int) {
super.characters(ch, start, length)
val strings = String(ch!!, start, length)
trim = strings.trim()
if (trim != "") {
println(trim)
}
}
SAX解析開始...
開始周遊第1 本書
屬性名為:id屬性值為:1
子節點名字為: name 子節點的值為: XML深入淺出
子節點名字為: author 子節點的值為: Imooc
子節點名字為: year 子節點的值為: 2014
子節點名字為: price 子節點的值為: 89
========================第1 本書周遊完成
開始周遊第2 本書
屬性名為:id屬性值為:2
子節點名字為: name 子節點的值為: Java從入門到精通
子節點名字為: author 子節點的值為: Imooc
子節點名字為: price 子節點的值為: 369
========================第2 本書周遊完成
SAX解析結束...
[
{
"id": 1,
"name": "XML深入淺出",
"author": "Imooc",
"year": "2014",
"price": "89"
},
{
"id": 2,
"name": "Java從入門到精通",
"author": "Imooc",
"year": null,
"price": "369"
}
]
3.JDOM
Maven依賴
<!-- https://mvnrepository.com/artifact/org.jdom/jdom -->
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom</artifactId>
<version>2.0.2</version>
</dependency>
主要代碼
package imooc.imooc.jdom
import com.google.gson.GsonBuilder
import imooc.Book
import org.jdom2.input.SAXBuilder
import org.junit.Test
import java.io.FileInputStream
import java.io.InputStreamReader
/**
* @author futao
* Created on 2017/11/3 - 13:41.
*/
class Jdom {
@Test
fun testJdom() {
val list = ArrayList<Book>()
var book = Book()
//1.建立一個SAXBuilder對象
val saxBuilder = SAXBuilder()
/*
* 亂碼解決方案
* 1.修改xml檔案的編碼格式
* 2.用InputStreamReader代替FileInputStream,設定編碼格式
* */
//2.通過輸入流的方式加載xml檔案到saxBuilder中
// val document = saxBuilder.build(FileInputStream("D:\\src\\springhibernate\\springshibernate\\src\\test\\resources\\books.xml"))
val document = saxBuilder.build(InputStreamReader(FileInputStream("D:\\src\\springhibernate\\springshibernate\\src\\test\\resources\\books.xml"), "UTF-8"))
//3.擷取根節點
val rootElement = document.rootElement
//4.根節點的子節點集合
val rootChildElement = rootElement.children
for (i in rootChildElement) {
println("==================== 開始解析第${rootChildElement.indexOf(i) + 1}本書==================== ")
book = Book()
//解析根節點的所有屬性
for (k in i.attributes) {
println(k.name + " : " + k.value)
assignment(book, k.name, k.value)
}
val children = i.children
//解析子節點和子節點的内容
for (j in children) {
println(j.name + " : " + j.value)
assignment(book, j.name, j.value)
}
list.add(book)
}
println(GsonBuilder().serializeNulls().setPrettyPrinting().create().toJson(list))
}
private fun assignment(book: Book, property: String, value: String): Book {
when (property) {
"id" -> book.id = value.toInt()
"name" -> book.name = value
"author" -> book.author = value
"year" -> book.year = value
"price" -> book.price = value
}
return book
}
}
==================== 開始解析第1本書====================
id : 1
name : XML深入淺出
author : Imooc
year : 2014
price : 89
==================== 開始解析第2本書====================
id : 2
name : Java從入門到精通
author : Imooc
price : 369
Disconnected from the target VM, address: '127.0.0.1:59271', transport: 'socket'
[
{
"id": 1,
"name": "XML深入淺出",
"author": "Imooc",
"year": "2014",
"price": "89"
},
{
"id": 2,
"name": "Java從入門到精通",
"author": "Imooc",
"year": null,
"price": "369"
}
]
4.DOM4J
maven依賴
<!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
package imooc.imooc.dom4j
import com.google.gson.GsonBuilder
import imooc.Book
import org.dom4j.Attribute
import org.dom4j.Element
import org.dom4j.io.SAXReader
import org.junit.Test
import java.io.File
/**
* @author futao
* Created on 2017/11/3 - 14:37.
*/
class DOM4JTest {
@Test
fun testDOM4J() {
val list = ArrayList<Book>()
var book = Book()
val saxReader = SAXReader()
val document = saxReader.read(File("D:\\src\\springhibernate\\springshibernate\\src\\test\\resources\\books.xml"))
//根節點
val rootElement = document.rootElement
//通過Element的elementIterator()方法擷取疊代器
val elementIterator = rootElement.elementIterator()
//周遊疊代器,擷取根節點的子節點資訊
for ((index, i) in elementIterator.withIndex()) {
val element = i as Element
// println(element.name)
println("===============開始解析第${index + 1}本書===============")
book = Book()
//周遊子節點的屬性
i.attributes()
.map { it as Attribute }
.forEach {
println(it.name + " : " + it.value)
assignment(book, it.name, it.value)
}
//周遊子節點的子節點和内容
for (k in i.elementIterator()) {
k as Element
println(k.name + " : " + k.textTrim)
assignment(book, k.name, k.textTrim)
}
list.add(book)
}
println(GsonBuilder().serializeNulls().setPrettyPrinting().create().toJson(list))
}
private fun assignment(book: Book, property: String, value: String): Book {
when (property) {
"id" -> book.id = value.toInt()
"name" -> book.name = value
"author" -> book.author = value
"year" -> book.year = value
"price" -> book.price = value
}
return book
}
}
===============開始解析第1本書===============
id : 1
name : deep
name : XML深入淺出
author : Imooc
year : 2014
price : 89
===============開始解析第2本書===============
id : 2
name : Java從入門到精通
author : Imooc
price : 369
[
{
"id": 1,
"name": "XML深入淺出",
"author": "Imooc",
"year": "2014",
"price": "89"
},
{
"id": 2,
"name": "Java從入門到精通",
"author": "Imooc",
"year": null,
"price": "369"
}
]
讀取效率
@Test
fun efficiencyCompare() {
val startTime1 = System.currentTimeMillis()
testDOM4J()
println("DOM4J耗時: ${System.currentTimeMillis() - startTime1}")
val startTime2 = System.currentTimeMillis()
Jdom().testJdom()
println("JDOM耗時: ${System.currentTimeMillis() - startTime2}")
val startTime3 = System.currentTimeMillis()
XML().byDOM()
println("DOM耗時: ${System.currentTimeMillis() - startTime3}")
val startTime4 = System.currentTimeMillis()
XML().bySAX()
println("SAX耗時: ${System.currentTimeMillis() - startTime4}")
}
DOM4J耗時: 379
JDOM耗時: 141
DOM耗時: 52
SAX耗時: 32