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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: des...四种解析方式:DOMSAXJDOMDOM4J解析目标-books.xml文件 XML深入浅出 Imooc 2014 89 Java从入门到精通 Imooc 369 1.

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
目录
相关文章
|
7天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
23 2
|
11天前
|
Java
轻松上手Java字节码编辑:IDEA插件VisualClassBytes全方位解析
本插件VisualClassBytes可修改class字节码,包括class信息、字段信息、内部类,常量池和方法等。
60 6
|
8天前
|
存储 算法 Java
Java Set深度解析:为何它能成为“无重复”的代名词?
Java的集合框架中,Set接口以其“无重复”特性著称。本文解析了Set的实现原理,包括HashSet和TreeSet的不同数据结构和算法,以及如何通过示例代码实现最佳实践。选择合适的Set实现类和正确实现自定义对象的hashCode()和equals()方法是关键。
20 4
|
12天前
|
Java Maven
maven项目的pom.xml文件常用标签使用介绍
第四届人文,智慧教育与服务管理国际学术会议(HWESM 2025) 2025 4th International Conference on Humanities, Wisdom Education and Service Management
64 8
|
11天前
|
Java 编译器 数据库连接
Java中的异常处理机制深度解析####
本文深入探讨了Java编程语言中异常处理机制的核心原理、类型及其最佳实践,旨在帮助开发者更好地理解和应用这一关键特性。通过实例分析,揭示了try-catch-finally结构的重要性,以及如何利用自定义异常提升代码的健壮性和可读性。文章还讨论了异常处理在大型项目中的最佳实践,为提高软件质量提供指导。 ####
|
15天前
|
存储 分布式计算 Java
存算分离与计算向数据移动:深度解析与Java实现
【11月更文挑战第10天】随着大数据时代的到来,数据量的激增给传统的数据处理架构带来了巨大的挑战。传统的“存算一体”架构,即计算资源与存储资源紧密耦合,在处理海量数据时逐渐显露出其局限性。为了应对这些挑战,存算分离(Disaggregated Storage and Compute Architecture)和计算向数据移动(Compute Moves to Data)两种架构应运而生,成为大数据处理领域的热门技术。
37 2
|
15天前
|
存储 Java 开发者
Java中的集合框架深入解析
【10月更文挑战第32天】本文旨在为读者揭开Java集合框架的神秘面纱,通过深入浅出的方式介绍其内部结构与运作机制。我们将从集合框架的设计哲学出发,探讨其如何影响我们的编程实践,并配以代码示例,展示如何在真实场景中应用这些知识。无论你是Java新手还是资深开发者,这篇文章都将为你提供新的视角和实用技巧。
12 0
|
1月前
|
JSON 调度 数据库
Android面试之5个Kotlin深度面试题:协程、密封类和高阶函数
本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点。文章详细解析了Kotlin中的协程、扩展函数、高阶函数、密封类及`inline`和`reified`关键字在Android开发中的应用,帮助读者更好地理解和使用这些特性。
22 1
|
2月前
|
Android开发 开发者 Kotlin
告别AsyncTask:一招教你用Kotlin协程重构Android应用,流畅度飙升的秘密武器
【9月更文挑战第13天】随着Android应用复杂度的增加,有效管理异步任务成为关键。Kotlin协程提供了一种优雅的并发操作处理方式,使异步编程更简单直观。本文通过具体示例介绍如何使用Kotlin协程优化Android应用性能,包括网络数据加载和UI更新。首先需在`build.gradle`中添加coroutines依赖。接着,通过定义挂起函数执行网络请求,并在`ViewModel`中使用`viewModelScope`启动协程,结合`Dispatchers.Main`更新UI,避免内存泄漏。使用协程不仅简化代码,还提升了程序健壮性。
81 1
|
3月前
|
调度 Android开发 开发者
【颠覆传统!】Kotlin协程魔法:解锁Android应用极速体验,带你领略多线程优化的无限魅力!
【8月更文挑战第12天】多线程对现代Android应用至关重要,能显著提升性能与体验。本文探讨Kotlin中的高效多线程实践。首先,理解主线程(UI线程)的角色,避免阻塞它。Kotlin协程作为轻量级线程,简化异步编程。示例展示了如何使用`kotlinx.coroutines`库创建协程,执行后台任务而不影响UI。此外,通过协程与Retrofit结合,实现了网络数据的异步加载,并安全地更新UI。协程不仅提高代码可读性,还能确保程序高效运行,不阻塞主线程,是构建高性能Android应用的关键。
61 4

推荐镜像

更多
下一篇
无影云桌面