des...
四種解析方式:
DOM
SAX
JDOM
DOM4J
解析目標(biāo)-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.創(chuàng)建一個(gè)DocumentBuilderFactory對(duì)象
val builderFactory = DocumentBuilderFactory.newInstance()
try {
//2.創(chuàng)建一個(gè)DocumentBuilder
val documentBuilder = builderFactory.newDocumentBuilder()
//通過(guò)DocumentBuilder對(duì)象的parse方法加載books.xml到當(dāng)前項(xiàng)目下
val parse = documentBuilder.parse("D:\\src\\springhibernate\\springshibernate\\src\\test\\kotlin\\imooc\\books.xml")
//獲取節(jié)點(diǎn)(book)的集合
val bookNodeList = parse.getElementsByTagName("book")
println("book節(jié)點(diǎn)個(gè)數(shù)為${bookNodeList.length}")
//遍歷每一個(gè)book節(jié)點(diǎn)
for (i in 0 until bookNodeList.length) {
//遍歷每個(gè)book節(jié)點(diǎn)的所有屬性的集合
val bookNodeAttributes = bookNodeList.item(i).attributes
for (j in 0 until bookNodeAttributes.length) {
println("第${i + 1} 個(gè)book節(jié)點(diǎn)公有${bookNodeList.item(i).attributes.length}個(gè)屬性")
println("屬性:" + bookNodeAttributes.item(j))
println(bookNodeAttributes.item(j).nodeName)
println(bookNodeAttributes.item(j).nodeValue)
//獲取當(dāng)前book節(jié)點(diǎn)的子節(jié)點(diǎn)集合
val bookNodeChildNodes = bookNodeList.item(i).childNodes
//會(huì)把空格和換行符也當(dāng)成節(jié)點(diǎn)
println("第${i + 1} 本書共有${(bookNodeChildNodes.length - 1) / 2}個(gè)子節(jié)點(diǎn)")
// for (k in 0 until (bookNodeChildNodes.length - 1) / 2) {
(0 until bookNodeChildNodes.length - 1)
.filter { bookNodeChildNodes.item(it).nodeType == Node.ELEMENT_NODE }
.forEach {
print("子節(jié)點(diǎn)" + bookNodeChildNodes.item(it).nodeName)
//null
// println(bookNodeChildNodes.item(it).nodeValue)
println(" 對(duì)應(yīng)的值為 " + bookNodeChildNodes.item(it).firstChild.nodeValue)
// println(" 對(duì)應(yīng)的值為 " + bookNodeChildNodes.item(it).textContent)
}
}
}
} catch (e: ParserConfigurationException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
} catch (e: SAXException) {
e.printStackTrace()
}
}
}
結(jié)果
book節(jié)點(diǎn)個(gè)數(shù)為2
第1 個(gè)book節(jié)點(diǎn)公有1個(gè)屬性
屬性:id="1"
id
1
第1 本書共有4個(gè)子節(jié)點(diǎn)
子節(jié)點(diǎn)name 對(duì)應(yīng)的值為 XML深入淺出
子節(jié)點(diǎn)author 對(duì)應(yīng)的值為 Imooc
子節(jié)點(diǎn)year 對(duì)應(yīng)的值為 2014
子節(jié)點(diǎn)price 對(duì)應(yīng)的值為 89
第2 個(gè)book節(jié)點(diǎn)公有1個(gè)屬性
屬性:id="2"
id
2
第2 本書共有3個(gè)子節(jié)點(diǎn)
子節(jié)點(diǎn)name 對(duì)應(yīng)的值為 Java從入門到精通
子節(jié)點(diǎn)author 對(duì)應(yīng)的值為 Imooc
子節(jié)點(diǎn)price 對(duì)應(yīng)的值為 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節(jié)點(diǎn)的索引
private var bookIndex = 0
//保存book對(duì)象
private var bookList = ArrayList<Book>()
//當(dāng)前的book對(duì)象
var book = Book()
//當(dāng)前文本內(nèi)容
var trim = ""
/**
* 遍歷xml的文件開(kāi)始標(biāo)簽
*/
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("開(kāi)始遍歷第$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("子節(jié)點(diǎn)名字為: $qName 子節(jié)點(diǎn)的值為: ")
}
}
/**
* 遍歷xml文件的結(jié)束標(biāo)簽
*/
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 本書遍歷完成")
}
}
/**
* 標(biāo)志解析開(kāi)始
*/
override fun startDocument() {
super.startDocument()
println("SAX解析開(kāi)始...")
}
/**
* 標(biāo)志解析結(jié)束
*/
override fun endDocument() {
super.endDocument()
println("SAX解析結(jié)束...")
println(GsonBuilder().serializeNulls().setPrettyPrinting().create().toJson(bookList))
}
/**
* 解析內(nèi)容罚舱,獲取文本
*/
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)
}
}
結(jié)果
SAX解析開(kāi)始...
開(kāi)始遍歷第1 本書
屬性名為:id屬性值為:1
子節(jié)點(diǎn)名字為: name 子節(jié)點(diǎn)的值為: XML深入淺出
子節(jié)點(diǎn)名字為: author 子節(jié)點(diǎn)的值為: Imooc
子節(jié)點(diǎn)名字為: year 子節(jié)點(diǎn)的值為: 2014
子節(jié)點(diǎn)名字為: price 子節(jié)點(diǎn)的值為: 89
========================第1 本書遍歷完成
開(kāi)始遍歷第2 本書
屬性名為:id屬性值為:2
子節(jié)點(diǎn)名字為: name 子節(jié)點(diǎn)的值為: Java從入門到精通
子節(jié)點(diǎn)名字為: author 子節(jié)點(diǎn)的值為: Imooc
子節(jié)點(diǎn)名字為: price 子節(jié)點(diǎn)的值為: 369
========================第2 本書遍歷完成
SAX解析結(jié)束...
[
{
"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.創(chuàng)建一個(gè)SAXBuilder對(duì)象
val saxBuilder = SAXBuilder()
/*
* 亂碼解決方案
* 1.修改xml文件的編碼格式
* 2.用InputStreamReader代替FileInputStream蔬顾,設(shè)置編碼格式
* */
//2.通過(guò)輸入流的方式加載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.獲取根節(jié)點(diǎn)
val rootElement = document.rootElement
//4.根節(jié)點(diǎn)的子節(jié)點(diǎn)集合
val rootChildElement = rootElement.children
for (i in rootChildElement) {
println("==================== 開(kāi)始解析第${rootChildElement.indexOf(i) + 1}本書==================== ")
book = Book()
//解析根節(jié)點(diǎn)的所有屬性
for (k in i.attributes) {
println(k.name + " : " + k.value)
assignment(book, k.name, k.value)
}
val children = i.children
//解析子節(jié)點(diǎn)和子節(jié)點(diǎn)的內(nèi)容
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
}
}
結(jié)果
==================== 開(kāi)始解析第1本書====================
id : 1
name : XML深入淺出
author : Imooc
year : 2014
price : 89
==================== 開(kāi)始解析第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"))
//根節(jié)點(diǎn)
val rootElement = document.rootElement
//通過(guò)Element的elementIterator()方法獲取迭代器
val elementIterator = rootElement.elementIterator()
//遍歷迭代器,獲取根節(jié)點(diǎn)的子節(jié)點(diǎn)信息
for ((index, i) in elementIterator.withIndex()) {
val element = i as Element
// println(element.name)
println("===============開(kāi)始解析第${index + 1}本書===============")
book = Book()
//遍歷子節(jié)點(diǎn)的屬性
i.attributes()
.map { it as Attribute }
.forEach {
println(it.name + " : " + it.value)
assignment(book, it.name, it.value)
}
//遍歷子節(jié)點(diǎn)的子節(jié)點(diǎn)和內(nèi)容
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
}
}
結(jié)果
===============開(kāi)始解析第1本書===============
id : 1
name : deep
name : XML深入淺出
author : Imooc
year : 2014
price : 89
===============開(kāi)始解析第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耗時(shí): ${System.currentTimeMillis() - startTime1}")
val startTime2 = System.currentTimeMillis()
Jdom().testJdom()
println("JDOM耗時(shí): ${System.currentTimeMillis() - startTime2}")
val startTime3 = System.currentTimeMillis()
XML().byDOM()
println("DOM耗時(shí): ${System.currentTimeMillis() - startTime3}")
val startTime4 = System.currentTimeMillis()
XML().bySAX()
println("SAX耗時(shí): ${System.currentTimeMillis() - startTime4}")
}
結(jié)果
DOM4J耗時(shí): 379
JDOM耗時(shí): 141
DOM耗時(shí): 52
SAX耗時(shí): 32