XML DOM – 节点列表和命名节点图(保姆级教程)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
在现代软件开发中,数据的存储和交换是核心任务之一。XML(可扩展标记语言)因其灵活的结构和跨平台兼容性,成为数据描述的常用标准。而XML DOM(文档对象模型)则提供了一种通过编程方式操作XML文档的接口,让开发者能够高效地访问、修改和查询节点。然而,许多开发者在使用DOM时,容易对节点列表(NodeList)和命名节点图(NamedNodeMap)这两个概念感到困惑。本文将通过 循序渐进的方式,结合 实际案例和代码示例,帮助读者理解这两个核心概念,并掌握如何在实际项目中应用它们。
XML DOM 基础:文档结构与节点
在深入讲解节点列表和命名节点图之前,我们需要先了解XML DOM的基本结构。
XML 文档的树形结构
XML文档可以视为一棵树,每个节点(Node)代表文档中的一个元素、属性或文本内容。例如,以下XML片段:
<library>
<book id="1">
<title>Effective JavaScript</title>
<author>David Herman</author>
</book>
</library>
该文档包含多个节点:
library
是根节点(根元素)。book
是子节点,属于library
的子元素。title
和author
是book
的子节点。id="1"
是book
元素的属性,属于属性节点。
节点的类型与关系
XML DOM中的节点类型包括:
- 元素节点(Element Node):如
<book>
。 - 属性节点(Attribute Node):如
id="1"
。 - 文本节点(Text Node):如
<title>
标签内的文本内容。 - 注释节点(Comment Node):如
<!-- 这是注释 -->
。
节点之间通过父子关系、兄弟关系连接。例如,book
是 library
的子节点,而 title
和 author
是兄弟节点。
节点列表(NodeList):动态的节点集合
节点列表(NodeList)是一个类似数组的对象,用于存储一组节点。它通常由DOM方法(如 getElementsByTagName
)返回,表示对文档中某一类节点的引用。
NodeList 的特性与操作
特性
- 动态性:NodeList是“实时”的,如果文档中的节点被修改(如新增或删除),NodeList的内容会自动更新。
- 类数组结构:支持通过索引访问元素(如
nodes[0]
),但不包含数组方法(如map
或filter
)。
常见操作方法
方法/属性 | 说明 |
---|---|
length | 返回节点列表中元素的数量 |
item(index) | 通过索引获取节点(等价于 nodes[index] ) |
实例:遍历所有书籍
以下代码演示如何使用 getElementsByTagName
获取所有 <book>
节点,并遍历输出其标题:
const xmlString = `
<library>
<book id="1">
<title>Effective JavaScript</title>
</book>
<book id="2">
<title>You Don't Know JS</title>
</book>
</library>`;
// 解析XML
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlString, "application/xml");
// 获取所有book元素(返回NodeList)
const books = xmlDoc.getElementsByTagName("book");
// 遍历节点列表
for (let i = 0; i < books.length; i++) {
const title = books[i].getElementsByTagName("title")[0].textContent;
console.log(`Book ${i + 1}: ${title}`);
}
输出结果:
Book 1: Effective JavaScript
Book 2: You Don't Know JS
类比:节点列表就像图书馆的书架
想象一个图书馆的书架,所有书籍按类别排列。NodeList就像这个书架:
- 你可以通过编号(索引)快速找到某本书。
- 如果有人新放了一本书到书架上,NodeList会自动包含它。
- 但NodeList本身不提供“排序”或“过滤”功能,需要手动遍历处理。
命名节点图(NamedNodeMap):键值对属性集合
命名节点图(NamedNodeMap)用于存储具有唯一名称的节点集合,最常见的是元素的属性。例如,<book id="1">
的 id
属性即存储在 book
的 attributes
属性中。
NamedNodeMap 的特性与操作
特性
- 键值对结构:每个节点由名称(如
id
)和值(如"1"
)组成,类似字典或对象。 - 动态性:与NodeList一样,属性的修改会实时反映在NamedNodeMap中。
- 不可迭代:不支持
for...of
或forEach
,需通过属性名或索引访问。
常见操作方法
方法/属性 | 说明 |
---|---|
getNamedItem(name) | 通过名称获取属性节点 |
item(index) | 通过索引获取属性节点 |
removeNamedItem(name) | 移除指定名称的属性节点 |
实例:操作元素属性
以下代码演示如何通过 attributes
获取和修改属性:
// 假设xmlDoc已如前文定义
const firstBook = xmlDoc.getElementsByTagName("book")[0];
// 获取属性集合
const attrs = firstBook.attributes;
// 输出所有属性
for (let i = 0; i < attrs.length; i++) {
const attr = attrs.item(i);
console.log(`Attribute Name: ${attr.name}, Value: ${attr.value}`);
}
// 修改属性值
const idAttr = attrs.getNamedItem("id");
idAttr.value = "99";
// 添加新属性
const newAttr = xmlDoc.createAttribute("category");
newAttr.value = "Programming";
firstBook.setAttributeNode(newAttr);
输出结果:
Attribute Name: id, Value: 1
Attribute Name: category, Value: Programming
类比:命名节点图就像图书馆的分类标签
假设每本书都有一个标签,标注其分类、作者等信息。NamedNodeMap就像这些标签:
- 每个标签有唯一的名称(如“分类”),对应一个值(如“编程”)。
- 你可以通过名称快速查找或修改标签内容,但需要手动遍历所有标签。
节点列表与命名节点图的对比
特征 | 节点列表(NodeList) | 命名节点图(NamedNodeMap) |
---|---|---|
存储内容 | 任意类型的节点集合(如元素、文本) | 仅属性节点 |
访问方式 | 索引(nodes[0] )或 item(index) | 索引或名称(getNamedItem(name) ) |
动态性 | 是 | 是 |
常见使用场景 | 遍历元素列表(如所有 <book> ) | 访问元素的属性集合 |
实战案例:构建XML数据解析器
假设我们需要从XML文档中提取书籍信息,并生成一个包含标题、ID和分类的JSON对象。以下是完整代码示例:
const xmlString = `
<library>
<book id="1" category="Programming">
<title>Effective JavaScript</title>
<author>David Herman</author>
</book>
<book id="2" category="Web Dev">
<title>You Don't Know JS</title>
<author>Kyle Simpson</author>
</book>
</library>`;
const xmlDoc = new DOMParser().parseFromString(xmlString, "application/xml");
const booksNodeList = xmlDoc.getElementsByTagName("book");
const booksJSON = [];
for (let i = 0; i < booksNodeList.length; i++) {
const bookNode = booksNodeList[i];
const attrs = bookNode.attributes;
// 提取属性
const id = attrs.getNamedItem("id").value;
const category = attrs.getNamedItem("category").value;
// 提取子元素内容
const titleNode = bookNode.getElementsByTagName("title")[0];
const title = titleNode.textContent;
booksJSON.push({
id,
category,
title
});
}
console.log(JSON.stringify(booksJSON, null, 2));
输出结果:
[
{
"id": "1",
"category": "Programming",
"title": "Effective JavaScript"
},
{
"id": "2",
"category": "Web Dev",
"title": "You Don't Know JS"
}
]
结论:掌握核心概念,提升DOM操作效率
通过本文的讲解,我们明确了 XML DOM – 节点列表和命名节点图 的核心作用:
- 节点列表(NodeList) 是动态的节点集合,适用于遍历元素或文本节点。
- 命名节点图(NamedNodeMap) 是属性的键值对存储,提供高效的属性访问与修改能力。
- 结合两者,开发者能够灵活解析和操作XML文档,满足数据提取、转换等需求。
对于初学者,建议从简单案例入手,逐步实践DOM方法(如 getElementsByTagName
、getAttribute
)。中级开发者则可以探索更复杂的场景,例如结合XPath实现高级查询,或通过NodeList和NamedNodeMap优化数据处理流程。掌握这些基础,将为处理XML相关的复杂项目打下坚实的基础。