Android中使用DOM方式解析XML文件
在Android开发中,XML是常用的数据交换格式,比如接口返回的配置信息、本地存储的结构化数据等场景都会用到XML。DOM(Document Object Model,文档对象模型)是解析XML的常用方式之一,它的核心思路是把整个XML文档加载到内存中,构建成一个树形结构,之后我们可以通过节点遍历的方式获取想要的数据。这种方式适合解析体积较小的XML文件,优点是操作直观、可以随机访问任意节点,缺点是内存占用相对较高,不适合大文件解析。
DOM解析XML的核心流程
使用DOM解析XML的整体步骤可以分为以下几步:
- 获取XML数据来源,可以是本地assets目录下的文件,也可以是网络请求返回的流
- 创建DocumentBuilderFactory实例,再通过它获取DocumentBuilder
- 使用DocumentBuilder解析XML数据,得到Document对象(也就是整个XML的树形结构根节点)
- 通过Document对象获取目标节点列表,遍历节点提取内容
- 解析完成后关闭相关流,释放资源
准备测试XML文件
我们首先在Android项目的assets目录下创建一个名为user_info.xml的测试文件,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<users>
<user id="1">
<name>张三</name>
<age>25</age>
<email>zhangsan@ipipp.com</email>
</user>
<user id="2">
<name>李四</name>
<age>28</age>
<email>lisi@ipipp.com</email>
</user>
</users>这个XML的根节点是<users>,下面包含两个<user>子节点,每个<user>节点有id属性,同时包含<name>、<age>、<email>三个子节点,我们后续就解析这个文件的内容。
DOM解析XML的完整实现代码
下面是在Android中通过DOM解析上述XML文件的完整代码示例,我们创建一个工具类来完成解析逻辑:
import android.content.Context;
import android.content.res.AssetManager;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
public class DomXmlParser {
/**
* 解析assets目录下的user_info.xml文件
* @param context 上下文对象,用于获取AssetManager
* @return 解析得到的用户列表
*/
public static List<User> parseXmlFromAssets(Context context) {
List<User> userList = new ArrayList<>();
DocumentBuilderFactory factory = null;
InputStream inputStream = null;
try {
// 1. 获取assets目录下的XML文件输入流
AssetManager assetManager = context.getAssets();
inputStream = assetManager.open("user_info.xml");
// 2. 创建DocumentBuilderFactory和DocumentBuilder
factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
// 3. 解析输入流,得到Document对象
Document document = builder.parse(inputStream);
// 规范化XML格式,避免空白节点干扰
document.getDocumentElement().normalize();
// 4. 获取所有user节点
NodeList userNodeList = document.getElementsByTagName("user");
// 5. 遍历user节点,提取每个用户的信息
for (int i = 0; i < userNodeList.getLength(); i++) {
Node userNode = userNodeList.item(i);
// 判断节点类型是否为元素节点
if (userNode.getNodeType() == Node.ELEMENT_NODE) {
Element userElement = (Element) userNode;
User user = new User();
// 获取user节点的id属性
String userId = userElement.getAttribute("id");
user.setId(Integer.parseInt(userId));
// 获取name子节点的内容
NodeList nameNodeList = userElement.getElementsByTagName("name");
if (nameNodeList.getLength() > 0) {
user.setName(nameNodeList.item(0).getTextContent());
}
// 获取age子节点的内容
NodeList ageNodeList = userElement.getElementsByTagName("age");
if (ageNodeList.getLength() > 0) {
user.setAge(Integer.parseInt(ageNodeList.item(0).getTextContent()));
}
// 获取email子节点的内容
NodeList emailNodeList = userElement.getElementsByTagName("email");
if (emailNodeList.getLength() > 0) {
user.setEmail(emailNodeList.item(0).getTextContent());
}
userList.add(user);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 6. 关闭输入流,释放资源
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return userList;
}
/**
* 用户实体类,用于存储解析后的用户信息
*/
public static class User {
private int id;
private String name;
private int age;
private String email;
// getter和setter方法
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{id=" + id + ", name='" + name + "', age=" + age + ", email='" + email + "'}";
}
}
}代码中的User是内部实体类,用来存储每个用户的属性。解析逻辑里首先通过getElementsByTagName方法获取所有<user>节点,然后遍历每个节点,通过getAttribute获取属性值,再通过子标签名获取对应的内容节点,最后调用getTextContent拿到节点的文本内容。
调用解析方法并验证结果
我们可以在Activity中调用上述解析方法,把结果打印出来验证是否正确:
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "DomXmlParseDemo";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 调用解析方法
List<DomXmlParser.User> userList = DomXmlParser.parseXmlFromAssets(this);
// 打印解析结果
for (DomXmlParser.User user : userList) {
Log.d(TAG, user.toString());
}
}
}运行应用后,可以在Logcat中看到如下输出,说明解析成功:
D/DomXmlParseDemo: User{id=1, name='张三', age=25, email='zhangsan@ipipp.com'}
D/DomXmlParseDemo: User{id=2, name='李四', age=28, email='lisi@ipipp.com'}DOM解析的注意事项
- DOM解析会把整个XML加载到内存,所以如果XML文件体积过大,可能会导致OOM(内存溢出),这种场景建议选择SAX或者Pull解析方式
- 调用
normalize方法可以规范XML格式,避免解析时出现多余的空白文本节点,减少不必要的判断逻辑 - 遍历节点时一定要先判断节点类型,避免处理到非元素节点导致类型转换异常
- 解析完成后务必关闭输入流,避免资源泄漏
- 如果解析网络请求的XML流,需要注意添加网络权限,并且在子线程中执行解析操作,避免阻塞主线程
AndroidDOM解析XMLXML解析DocumentBuilderassets目录 本作品最后修改时间:2026-05-22 21:18:13