如何检查DOM节点是否代表doctype声明的节点?

8

假设我们有一个文档(在IE8中),那么通常我们可以假定document.childNodes[0]是文档类型。因此

var doctype = document.childNodes[0]

现在,我们如何确认它确实是文档类型,而不是仅仅假设呢?

doctype.nodeType === Node.COMMENT_NODE;
doctype.tagName === "!"; // same as a comment
doctype.data.indexOf("DOCTYPE ") > -1; // same as any comment containing the word DOCTYPE.
doctype === document.doctype; // false, document.doctype is undefined in IE8

除了假设,我怎么知道给定的节点是否是文档类型?
对于不熟悉DOM4的人,请参阅DocumentType DOM-shim在IE8中通过返回document.childNodes [0]来获取document.doctype

4
文档类型声明(doctype)是否真的是文档对象模型(DOM)的一部分?我以为它不是,但我可能错了。 - Pekka
在Chrome/Mac中,节点类型为Node.DOCUMENT_TYPE_NODE - millimoose
4
是的,就在这个页面上检查一下document.childNodes[0]是什么。 - millimoose
@Pekka 还有 document.doctype - Raynos
@Alohci 我明白了。IE8没有文档节点的概念,它只在document.childNodes[0]处有注释。这是一个悲伤的日子。IE8又做错了一件事 :( - Raynos
显示剩余9条评论
2个回答

2
我发现在IE7和IE8中,对于注释节点,.innerHTML属性总是完整的"<!--comment here-->",而对于文档类型节点,则是""。即使是空注释,.innerHTML也是"<!---->"
因此,基于这个情况,我创建了:
function isDocType(node) {
    return node && (
    node.nodeType === 10 || (node.nodeType === 8 && "innerHTML" in node && node.innerHTML === ""));
}

使用测试页面:

<!-- comment1 -->
<!-- comment2 -->
<!---->
<!-- -->
<!-- <!DOCTYPE html> -->

将文档类型和注释传递给isDocType函数后得到:

LOG: true 
LOG: false 
LOG: false 
LOG: false 
LOG: false 
LOG: false

请参阅http://jsfiddle.net/AEYt4/。

哇,你是怎么发现这个的? - Florian Margaine
1
@FlorianMargaine 我使用了 console.dir,然后在 Excel 中将它们并排进行了比较。 - Esailija

0

IE8说不行。 :(

严肃地讲,除了使用黑科技和假设之外,没有干净的方法。

如评论所建议的,您可以假设注释不像文档类型那样

doctype.data.indexOf("<!DOCTYPE html") !== -1 && doctype.data.indexOf(">") !== -1

或者对DOM结构进行假设

我认为只有注释节点(以及解析器视为注释节点的任何内容,例如xml声明)可以在文档类型之前出现

因此,您可以只需循环遍历document.childNodes 中的注释节点,直到找到与上述正则表达式匹配的节点。


不,你不应该寻找注释节点。你应该具体寻找 node.nodeType === 10 (DOCUMENT_TYPE_NODE)。任何其他类型都是不正确的实现,最好忽略它们。 - user1385191
我相信任何实际上具有 nodeType === 10 的文档类型节点的浏览器都有 document.doctype - Raynos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接