Kotlin/Java解析XMl文件的四種方式

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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市琅束,隨后出現(xiàn)的幾起案子鹉胖,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惩淳,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡乓搬,警方通過(guò)查閱死者的電腦和手機(jī)思犁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)进肯,“玉大人激蹲,你說(shuō)我怎么就攤上這事〗冢” “怎么了学辱?”我有些...
    開(kāi)封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)环形。 經(jīng)常有香客問(wèn)我策泣,道長(zhǎng),這世上最難降的妖魔是什么抬吟? 我笑而不...
    開(kāi)封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任萨咕,我火速辦了婚禮,結(jié)果婚禮上火本,老公的妹妹穿的比我還像新娘危队。我一直安慰自己聪建,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布茫陆。 她就那樣靜靜地躺著金麸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪簿盅。 梳的紋絲不亂的頭發(fā)上钱骂,一...
    開(kāi)封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音挪鹏,去河邊找鬼见秽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛讨盒,可吹牛的內(nèi)容都是我干的解取。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼返顺,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼禀苦!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起遂鹊,我...
    開(kāi)封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤振乏,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后秉扑,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體慧邮,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年舟陆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了误澳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡秦躯,死狀恐怖忆谓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情踱承,我是刑警寧澤倡缠,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站茎活,受9級(jí)特大地震影響昙沦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜妙色,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一桅滋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦丐谋、人聲如沸芍碧。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)泌豆。三九已至,卻和暖如春吏饿,著一層夾襖步出監(jiān)牢的瞬間踪危,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工猪落, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贞远,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓笨忌,卻偏偏與公主長(zhǎng)得像蓝仲,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子官疲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容