Kotlin解析XML的常见场景
在Kotlin开发中,XML解析常见于Android应用读取本地配置文件、解析服务端返回的XML格式接口数据、处理第三方系统的XML格式数据交换等场景。不同的场景对解析性能和代码简洁度的要求不同,选择合适的解析方式能大幅降低开发成本。

使用XmlPullParser解析XML
XmlPullParser是Android系统内置的XML解析器,属于轻量级的拉式解析器,不需要一次性把整个XML加载到内存中,适合解析较大的XML文件,在Kotlin中使用起来也比较简洁。
实现步骤
首先获取XmlPullParser实例,然后设置输入源,通过循环遍历解析事件,根据事件类型处理对应的节点内容。
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserFactory
import java.io.StringReader
// 待解析的XML字符串
val xmlData = """
<users>
<user>
<id>1</id>
<name>张三</name>
<age>25</age>
</user>
<user>
<id>2</id>
<name>李四</name>
<age>30</age>
</user>
</users>
""".trimIndent()
fun parseXmlWithPull() {
val factory = XmlPullParserFactory.newInstance()
val parser = factory.newPullParser()
parser.setInput(StringReader(xmlData))
var eventType = parser.eventType
var currentUserId = 0
var currentUserName = ""
var currentUserAge = 0
val userList = mutableListOf<Map<String, Any>>()
while (eventType != XmlPullParser.END_DOCUMENT) {
when (eventType) {
XmlPullParser.START_TAG -> {
when (parser.name) {
"id" -> currentUserId = parser.nextText().toInt()
"name" -> currentUserName = parser.nextText()
"age" -> currentUserAge = parser.nextText().toInt()
}
}
XmlPullParser.END_TAG -> {
if (parser.name == "user") {
userList.add(mapOf(
"id" to currentUserId,
"name" to currentUserName,
"age" to currentUserAge
))
}
}
}
eventType = parser.next()
}
println(userList)
}
// 调用方法
parseXmlWithPull()
使用DOM解析XML
DOM解析会把整个XML文档加载到内存中,形成一棵DOM树,开发者可以通过节点遍历的方式获取内容,代码逻辑比较直观,适合解析较小的XML文件。
实现示例
Kotlin中可以使用Java标准库的javax.xml.parsers.DocumentBuilder来实现DOM解析。
import javax.xml.parsers.DocumentBuilderFactory
import java.io.StringReader
import org.w3c.dom.Document
import org.w3c.dom.NodeList
fun parseXmlWithDom() {
val factory = DocumentBuilderFactory.newInstance()
val builder = factory.newDocumentBuilder()
val document: Document = builder.parse(org.xml.sax.InputSource(StringReader(xmlData)))
document.documentElement.normalize()
val userNodes: NodeList = document.getElementsByTagName("user")
val userList = mutableListOf<Map<String, Any>>()
for (i in 0 until userNodes.length) {
val userNode = userNodes.item(i)
val childNodes = userNode.childNodes
var id = 0
var name = ""
var age = 0
for (j in 0 until childNodes.length) {
val childNode = childNodes.item(j)
if (childNode.nodeType == org.w3c.dom.Node.ELEMENT_NODE) {
when (childNode.nodeName) {
"id" -> id = childNode.textContent.toInt()
"name" -> name = childNode.textContent
"age" -> age = childNode.textContent.toInt()
}
}
}
userList.add(mapOf("id" to id, "name" to name, "age" to age))
}
println(userList)
}
parseXmlWithDom()
使用SAX解析XML
SAX是事件驱动的解析方式,同样不需要加载整个XML到内存,适合解析大文件,需要自定义处理器来处理解析事件。
import org.xml.sax.Attributes
import org.xml.sax.helpers.DefaultHandler
import javax.xml.parsers.SAXParserFactory
import java.io.StringReader
class UserSaxHandler : DefaultHandler() {
private val userList = mutableListOf<Map<String, Any>>()
private var currentUserId = 0
private var currentUserName = ""
private var currentUserAge = 0
private var currentTag = ""
override fun startElement(uri: String?, localName: String?, qName: String?, attributes: Attributes?) {
currentTag = qName ?: ""
}
override fun characters(ch: CharArray?, start: Int, length: Int) {
val content = String(ch!!, start, length).trim()
if (content.isNotEmpty()) {
when (currentTag) {
"id" -> currentUserId = content.toInt()
"name" -> currentUserName = content
"age" -> currentUserAge = content.toInt()
}
}
}
override fun endElement(uri: String?, localName: String?, qName: String?) {
if (qName == "user") {
userList.add(mapOf(
"id" to currentUserId,
"name" to currentUserName,
"age" to currentUserAge
))
}
currentTag = ""
}
fun getResult() = userList
}
fun parseXmlWithSax() {
val factory = SAXParserFactory.newInstance()
val parser = factory.newSAXParser()
val handler = UserSaxHandler()
parser.parse(org.xml.sax.InputSource(StringReader(xmlData)), handler)
println(handler.getResult())
}
parseXmlWithSax()
不同解析方式的对比
| 解析方式 | 内存占用 | 代码复杂度 | 适用场景 |
|---|---|---|---|
| XmlPullParser | 低 | 中等 | Android平台解析中大型XML文件 |
| DOM解析 | 高 | 低 | 解析小型XML文件,需要随机访问节点 |
| SAX解析 | 低 | 较高 | 解析大型XML文件,只需要顺序读取 |
第三方库简化解析
如果不想手写解析逻辑,也可以使用第三方库比如Jackson XML或者Simple XML,通过注解的方式直接将XML映射到Kotlin数据类,大幅减少代码量。
// 以Jackson XML为例,首先添加依赖:implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.2")
import com.fasterxml.jackson.dataformat.xml.XmlMapper
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement
@JacksonXmlRootElement(localName = "users")
data class Users(
@JacksonXmlElementWrapper(useWrapping = false)
@JacksonXmlProperty(localName = "user")
val user: List<User>? = null
)
data class User(
@JacksonXmlProperty(localName = "id")
val id: Int? = null,
@JacksonXmlProperty(localName = "name")
val name: String? = null,
@JacksonXmlProperty(localName = "age")
val age: Int? = null
)
fun parseXmlWithJackson() {
val xmlMapper = XmlMapper()
val users = xmlMapper.readValue(xmlData, Users::class.java)
println(users.user)
}
parseXmlWithJackson()
KotlinXML解析DOM解析SAX解析XmlPullParser修改时间:2026-07-11 05:03:13