XML DOM – Element 对象
Element(元素节点)是 XML DOM 中最核心、最常用的节点类型,几乎所有的实际数据都位于 Element 节点及其后代中。
节点类型常量:
node.nodeType === 1 // Node.ELEMENT_NODE
1. 基本属性
| 属性 | 说明 | 只读 | 常用性 |
|---|---|---|---|
| nodeName | 标签名(大写形式在 XML 中区分大小写,保持原样) | 是 | ★★★★★ |
| tagName | 等同于 nodeName(在 XML 中完全相同) | 是 | ★★★★★ |
| nodeValue | 始终为 null(元素没有值,值在文本子节点中) | 是 | |
| textContent | 获取或设置元素内所有文本内容(会递归所有后代) | 否 | ★★★★★ |
| innerHTML | 在 XML DOM 中不支持或行为不一致(慎用) | × | |
| outerHTML | 也不支持(XMLSerializer 替代) | × |
2. 标签名与命名空间相关属性
| 属性 | 说明 | 只读 |
|---|---|---|
| localName | 不含命名空间前缀的标签名 | 是 |
| prefix | 命名空间前缀(如 xlink:href 中的 “xlink”) | 是 |
| namespaceURI | 命名空间 URI(如 http://www.w3.org/1999/xlink) | 是 |
示例:
<svg xmlns:ink="http://www.inkscape.org">
<ink:layer id="layer1">内容</ink:layer>
</svg>
const layer = doc.querySelector("ink|layer");
layer.tagName // "ink:layer"
layer.localName // "layer"
layer.prefix // "ink"
layer.namespaceURI // "http://www.inkscape.org"
3. 属性操作(最重要!)
| 方法/属性 | 说明 | 推荐度 |
|---|---|---|
| getAttribute(name) | 获取属性值(返回字符串或 null) | ★★★★★ |
| setAttribute(name, value) | 设置属性(会自动转成字符串) | ★★★★★ |
| removeAttribute(name) | 删除属性 | ★★★★★ |
| hasAttribute(name) | 判断是否存在该属性 | ★★★★★ |
| getAttributeNS(ns, localName) | 获取带命名空间的属性 | ★★★★ |
| setAttributeNS(ns, qname, value) | 设置带命名空间的属性 | ★★★★ |
| attributes | NamedNodeMap 对象,包含所有属性节点(可通过 attr.name / attr.value) | ★★★ |
示例:
const root = doc.documentElement;
root.setAttribute("version", "2.0");
root.setAttribute("xml:lang", "zh-CN");
console.log(root.getAttribute("version")); // "2.0"
root.removeAttribute("version");
root.hasAttribute("xml:lang"); // true
// 命名空间属性
root.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink");
root.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "data.xml");
4. 子节点操作
| 方法 | 说明 |
|---|---|
| childNodes | 所有子节点(包括文本、注释等) |
| children | 仅子元素(Element)集合,HTMLCollection |
| firstChild / lastChild | 第一个/最后一个子节点 |
| firstElementChild / lastElementChild | 第一个/最后一个子元素 |
| appendChild(node) | 添加子节点到末尾 |
| insertBefore(newNode, refNode) | 在 refNode 前插入 |
| removeChild(node) | 删除子节点 |
| replaceChild(newNode, oldNode) | 替换子节点 |
5. 查找元素(超级实用)
| 方法 | 说明 | 支持命名空间 |
|---|---|---|
| getElementById(id) | 通过 id 属性查找(要求有 id 且文档有 DTD/Schema) | |
| getElementsByTagName(name) | 通过标签名查找,返回实时 HTMLCollection | |
| getElementsByTagNameNS(ns, name) | 带命名空间的标签查找 | ★★★★★ |
| querySelector(selector) | CSS 选择器(支持命名空间需特殊写法) | ★★★★ |
| querySelectorAll(selector) | 同上,返回静态 NodeList | ★★★★ |
命名空间在 CSS 选择器中的写法:
// 查找 xmlns:svg="http://www.w3.org/2000/svg" 中的 circle
doc.querySelector('svg|circle'); // 推荐(IE 不支持)
doc.querySelector('*[local-name()="circle"]'); // 兼容性最好
6. 创建与克隆
// 创建新元素(必须指定命名空间才能创建带前缀的元素)
const newElem = doc.createElementNS("http://www.w3.org/2000/svg", "svg:circle");
newElem.setAttribute("cx", "50");
newElem.setAttribute("cy", "50");
newElem.setAttribute("r", "40");
doc.documentElement.appendChild(newElem);
// 克隆元素
const clone = newElem.cloneNode(true); // true = 深度克隆
7. 完整实战示例
const xmlStr = `<?xml version="1.0" encoding="UTF-8"?>
<library xmlns="http://example.com/books">
<book id="1">
<title lang="zh">XML 入门</title>
<price currency="CNY">68.00</price>
</book>
</library>`;
const parser = new DOMParser();
const doc = parser.parseFromString(xmlStr, "text/xml");
// 修改默认命名空间元素
const library = doc.documentElement;
library.setAttribute("updated", new Date().toISOString());
// 添加新书
const newBook = doc.createElement("book");
newBook.setAttribute("id", "2");
const title = doc.createElement("title");
title.setAttribute("lang", "en");
title.textContent = "Mastering XML";
const price = doc.createElement("price");
price.setAttribute("currency", "USD");
price.textContent = "45.99";
newBook.appendChild(title);
newBook.appendChild(price);
library.appendChild(newBook);
// 序列化输出
const serializer = new XMLSerializer();
console.log(serializer.serializeToString(doc));
8. 注意事项(常踩坑点)
- XML 是大小写敏感的,tagName 完全保持原始大小写。
- HTML 的 innerHTML 在 XML DOM 中不可靠,改用 textContent 或 appendChild 构建内容。
- 必须使用 createElementNS 才能创建带命名空间的元素。
- 属性顺序不固定,attributes 是 NamedNodeMap,不是数组。
- querySelector 在 IE 中不支持
ns|tag写法,用 getElementsByTagNameNS 更稳妥。
总结:
XML DOM 中的 Element 是承载结构与数据的主体,核心操作围绕:
属性(set/get/removeAttribute) + 子节点操作 + 命名空间 + query/getElementsByTagNameNS
掌握这几点,你就能完全驾驭任何 XML 文档的读写。