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 的子元素。
  • titleauthorbook 的子节点。
  • id="1"book 元素的属性,属于属性节点。

节点的类型与关系

XML DOM中的节点类型包括:

  • 元素节点(Element Node):如 <book>
  • 属性节点(Attribute Node):如 id="1"
  • 文本节点(Text Node):如 <title> 标签内的文本内容。
  • 注释节点(Comment Node):如 <!-- 这是注释 -->

节点之间通过父子关系、兄弟关系连接。例如,booklibrary 的子节点,而 titleauthor 是兄弟节点。


节点列表(NodeList):动态的节点集合

节点列表(NodeList)是一个类似数组的对象,用于存储一组节点。它通常由DOM方法(如 getElementsByTagName)返回,表示对文档中某一类节点的引用。

NodeList 的特性与操作

特性

  • 动态性:NodeList是“实时”的,如果文档中的节点被修改(如新增或删除),NodeList的内容会自动更新。
  • 类数组结构:支持通过索引访问元素(如 nodes[0]),但不包含数组方法(如 mapfilter)。

常见操作方法

方法/属性说明
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 属性即存储在 bookattributes 属性中。

NamedNodeMap 的特性与操作

特性

  • 键值对结构:每个节点由名称(如 id)和值(如 "1")组成,类似字典或对象。
  • 动态性:与NodeList一样,属性的修改会实时反映在NamedNodeMap中。
  • 不可迭代:不支持 for...offorEach,需通过属性名或索引访问。

常见操作方法

方法/属性说明
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 – 节点列表和命名节点图 的核心作用:

  1. 节点列表(NodeList) 是动态的节点集合,适用于遍历元素或文本节点。
  2. 命名节点图(NamedNodeMap) 是属性的键值对存储,提供高效的属性访问与修改能力。
  3. 结合两者,开发者能够灵活解析和操作XML文档,满足数据提取、转换等需求。

对于初学者,建议从简单案例入手,逐步实践DOM方法(如 getElementsByTagNamegetAttribute)。中级开发者则可以探索更复杂的场景,例如结合XPath实现高级查询,或通过NodeList和NamedNodeMap优化数据处理流程。掌握这些基础,将为处理XML相关的复杂项目打下坚实的基础。

最新发布