1. dom
DOM 是 W3C(万维网联盟)的标准。
DOM 定义了访问 HTML 和 XML 文档的标准:
“W3C 文档对象模型 (DOM) 是中立于平台和语言的接口,它允许程序和脚本动态地访问和更新文档的内容、结构和样式。”
W3C DOM 标准被分为 3 个不同的部分:
- 核心 DOM - 针对任何结构化文档的标准模型
- XML DOM - 针对 XML 文档的标准模型
- HTML DOM - 针对 HTML 文档的标准模型
2. xml dom
根据 DOM,XML 文档中的每个成分都是一个节点。
DOM 是这样规定的:
- 整个文档是一个文档节点
- 每个 XML 标签是一个元素节点
- 包含在 XML 元素中的文本是文本节点
- 每一个 XML 属性是一个属性节点
- 注释属于注释节点
2.1 文本总是存储在文本节点中
在 DOM 处理中一个普遍的错误是,认为元素节点包含文本。
不过,元素节点的文本是存储在文本节点中的。
在这个例子中:2005,元素节点 ,拥有一个值为 “2005” 的文本节点。
“2005” 不是 元素的值!
3. HTML DOM
根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点:
- 整个文档是一个文档节点
- 每个 HTML 元素是元素节点
- HTML 元素内的文本是文本节点
- 每个 HTML 属性是属性节点
- 注释是注释节点
3.1 文本节点
DOM 处理中的常见错误是希望元素节点包含文本。
在本例中:
可通过节点的 innerHTML 属性来访问文本节点的值。
4. 节点与元素的区别
4.1 节点类型
我们要如何区分这些不同类型的节点? 答案在于DOM Node接口,尤其是Node.nodeType
属性。
Node.nodeType
可以具有代表节点类型的以下值之一:
- Node.ELEMENT_NODE
- Node.ATTRIBUTE_NODE
- Node.TEXT_NODE
- Node.CDATA_SECTION_NODE
- Node.PROCESSING_INSTRUCTION_NODE
- Node.COMMENT_NODE
- Node.DOCUMENT_NODE
- Node.DOCUMENT_TYPE_NODE
- Node.DOCUMENT_FRAGMENT_NODE
- Node.NOTATION_NODE
常量有意义地指示节点类型:例如Node.ELEMENT_NODE
代表元素节点,Node.TEXT_NODE
代表文本节点,Node.DOCUMENT_NODE
文档节点,依此类推。
4.2 DOM元素
掌握了DOM节点的知识之后,现在该区分DOM节点和元素了。
如果你了解节点术语,那么答案是显而易见的:元素是特定类型的节点 element (Node.ELEMENT_NODE)
,以及文档、注释、文本等类型。
简而言之,元素是使用HTML文档中的标记编写的节点。 <html>
,<head>
,<title>
,<body>
,<h2>
,<p>
都是元素,因为它们由标签表示。
文档类型,注释,文本节点不是元素,因为它们没有使用标签编写:
Node
是节点的构造函数,HTMLElement
是 JS DOM 中元素的构造函数。段落既是节点又是元素,它同时是Node
和HTMLElement
的实例
const paragraph = document.querySelector('p');
paragraph instanceof Node; // => true
paragraph instanceof HTMLElement; // => true
4.3 DOM属性:节点和元素
除了区分节点和元素之外,还需要区分只包含节点或只包含元素的DOM属性。
节点类型的以下属性评估为一个节点或节点集合(NodeList
):
node.parentNode; // Node or null
node.firstChild; // Node or null
node.lastChild; // Node or null
node.childNodes; // NodeList
但是,以下属性是元素或元素集合(HTMLCollection
):
node.parentElement; // HTMLElement or null
node.children; // HTMLCollection
由于node.childNodes
和node.children都返回子级列表,因此为什么要同时具有这两个属性? 好问题!
考虑以下包含某些文本的段落元素:
<p>
<b>Thank you</b> for visiting my web page!
</p>
打开演示,然后查看parapgraph节点的childNodes
和children
属性:
const paragraph = document.querySelector('p');
paragraph.childNodes; // NodeList: [HTMLElement, Text]
paragraph.children; // HTMLCollection: [HTMLElement]
paragraph.childNodes
集合包含2个节点: <b>Thank you</b>
,,以及for visiting my web page!
文本节点!
但是,paragraph.children
集合仅包含1个项目:<b>Thank you</b>
。
由于paragraph.children
仅包含元素,因此此处未包含文本节点,因为其类型是文本(Node.TEXT_NODE
),而不是元素(Node.ELEMENT_NODE
)。
同时拥有node.childNodes
和node.children
,我们可以选择要访问的子级集合:所有子级节点或仅子级是元素。
4.4 Xreces-c 中解析节点与元素
- 取得根节点:
DOMElement* root = doc->getDocumentElement();//root
- 取得元素或节点getFirstChild, getFirstElementChild
{//getFirstChild, getFirstElementChild
DOMElement* ele = root->getFirstElementChild();//元素
if (ele) {
//通过转码来取字符串
std::cout << "getFirstElementChild = "
<< XMLString::transcode(ele->getNodeName())
<< std::endl;
}
DOMNode* c = root->getFirstChild();//节点,打印出来是文本节点
if (c) {
//通过转码来取字符串
std::cout << "getFirstChild = "
<< XMLString::transcode(c->getNodeName())
<< std::endl;
std::cout << "getFirstChild value = "
<< XMLString::transcode(c->getNodeValue())//节点,打印出来是文本节点
<< std::endl;
}
}
5.总结
区分DOM中的节点与元素对于C++或JAVA中的XML或HTML解析非常重要。元素是有标签的,文本节点、注释节点不属于元素;元素属于节点。
参考: