Skip to content

XML DOM 高级

XML 文档对象模型(DOM)提供了访问和操作 XML 文档结构和内容的标准方法。前面已介绍基本遍历,本节将涵盖使用 DOM API(通常在 JavaScript 环境中)读取和修改 XML 数据的更高级技术。

注意:示例使用了网页浏览器中常见的标准 DOM 方法。现代 JavaScript 提供了便捷的替代方案,例如 querySelector 和 querySelectorAll,它们接受 CSS 选择器(有时也接受基本 XPath)进行节点选择,这通常能写出更简洁的代码。

假设 xmlDoc 是一个变量,它持有已解析的 XML DOM 对象(例如,通过 fetch 和 DOMParser 加载获得)。

要获取元素内部的文本内容:

使用特定的 DOM 遍历(现在较不常用):

// 获取第一个 <title> 元素
const firstTitleElement = xmlDoc.getElementsByTagName("title")[0];
// 访问其第一个子节点(这应该是一个文本节点)
const textNode = firstTitleElement.childNodes[0];
// 获取文本节点的值
const titleText = textNode.nodeValue;

使用更简单的 .textContent 属性(推荐):

// 直接获取第一个 <title> 元素的文本内容
const titleText = xmlDoc.getElementsByTagName("title")[0].textContent;

解释:.textContent 属性会方便地合并所有子节点的文本内容,这通常正是我们想要的。childNodes[0].nodeValue 方法更明确,但如果元素在文本之前包含注释或其他节点类型,则这种方法会比较脆弱。

要获取与元素关联的属性值:

// 获取第一个 <title> 元素
const firstTitleElement = xmlDoc.getElementsByTagName("title")[0];
// 获取其 'lang' 属性的值
const langValue = firstTitleElement.getAttribute("lang"); // 在示例中返回 "en"

如果属性不存在,getAttribute() 返回 null。

要修改元素的文本内容:

使用特定的 DOM 操作(较不常用):

// 获取第一个 <title> 元素的文本节点
const textNode = xmlDoc.getElementsByTagName("title")[0].childNodes[0];
// 更改其值
textNode.nodeValue = "Easy XML Cooking";

使用更简单的 .textContent 属性(推荐):

// 获取第一个 <title> 元素
const firstTitleElement = xmlDoc.getElementsByTagName("title")[0];
// 更改其文本内容
firstTitleElement.textContent = "Easy XML Cooking";

设置 .textContent 会用一个新的文本节点替换元素的所有现有子节点。

setAttribute() 方法用于添加新属性或更改现有属性的值。

// 获取所有 <book> 元素
const books = xmlDoc.getElementsByTagName("book");
// 为每本书添加/更新一个 'edition' 属性
for (let i = 0; i < books.length; i++) {
books[i].setAttribute("edition", "first");
}

如果 ‘edition’ 属性已经存在,其值将被更新为 ‘first’。如果不存在,则会创建该属性。

要向现有元素添加一个新元素(例如,<edition>First</edition>):

  1. 使用 createElement() 创建新的元素节点(<edition>)。
  2. 使用 createTextNode() 创建文本内容(First)。(或者,在创建元素后设置 .textContent)。
  3. 使用 appendChild() 将文本节点添加为新元素节点的子节点。
  4. 再次使用 appendChild() 将新元素(及其文本子节点)添加到目标父元素(例如,第一个 <book>)中。

示例:

// 1. 创建新的 <edition> 元素
const newElement = xmlDoc.createElement("edition");
// 2. 创建文本内容
const newText = xmlDoc.createTextNode("First");
// 3. 将文本附加到新元素
newElement.appendChild(newText);
// --- 或者使用 textContent(更简单)---
// const newElement = xmlDoc.createElement("edition");
// newElement.textContent = "First";
// -------------------------------------
// 4. 获取目标父元素(第一个 <book>)
const firstBook = xmlDoc.getElementsByTagName("book")[0];
// 5. 将新的 <edition> 元素附加到第一个 <book>
firstBook.appendChild(newElement);

要移除节点(元素、文本节点、注释等),需要获取该节点本身及其父节点的引用。然后使用父节点的 removeChild() 方法。

示例:从第一个 <book> 元素中移除第一个子节点(可以是文本、元素等):

// 获取第一个 <book> 元素
const firstBook = xmlDoc.getElementsByTagName("book")[0];
// 检查它是否有任何子节点
if (firstBook.hasChildNodes()) {
// 获取第一个子节点
const nodeToRemove = firstBook.childNodes[0];
// 使用父节点移除它
firstBook.removeChild(nodeToRemove);
}

重要注意事项:childNodes 集合包含 所有 节点类型,包括元素、文本节点(即使只包含空白字符)和注释。如果你假定 childNodes[0] 总是第一个 元素 子节点,这有时会导致意外结果。请注意解析器可能在元素之间创建的空白文本节点。如果你只想要元素子节点,请考虑使用 .children 属性或遍历 childNodes 并检查 nodeType。

查阅完整的 XML DOM 规范(例如,在 MDN Web 文档上)会揭示更多用于详细导航和操作的方法。