您的位置:首页 > 其它

跟随标准与Webkit源码探究DOM -- 获取元素之getElementsByTagName

2014-11-22 17:35 483 查看

按照标签名获取元素 --
getElementsByTagName

标准

DOM 1在
Element
Document
两个interface中均有定义,原型
NodeList getElementsByTagName(in DOMString tagname)
,指明按照先序遍历遇到的顺序排列,不会抛出任何异常,参数
"*"
返回对应document或者element下所有元素。注意这里指明返回的是一个live的仅含有
Element
NodeList


DOM 2里定义仍在
Element
Document
,增加了带namespace的
NodeList getElementsByTagNameNS(in DOMString namespaceURI, in DOMString localName)
Element
Document
),引入了
localName
的概念(只有
ELEMENT_NODE
ATTRIBUTE_NODE
才能有)。

DOM 3(
Document
Element
)特别声明XML应当对标签名的大小写敏感,非XML则依照文档类型自己对待大小写的风格来决定是否敏感。实际上浏览器对HTML都会先将标签转统一换成成小写后再去匹配,所以只能匹配到实际标签名为小写的元素。

WHATWG (
Document
,
Element
)将返回类型修改为了
HTMLCollection
,并解释了通过
localName
产生
HTMLCollection
的算法
。注意算法的第二步实际上规定了在非HTML文档里,标签名大小写敏感;而在HTML文档里,任何大小写的标签都会被统一转换成小写后再去匹配,所以只能匹配到实际标签名为小写的元素。

DOM 4(DocumentElement) 目前与 WHATWG 基本一致

DOM Tree Accessors

DOM 1DOM 2
HTMLDocument
interface 里定义了一系列"DOM Tree Accessors"

readonly attribute HTMLCollection images


readonly attribute HTMLCollection applets


readonly attribute HTMLCollection links


readonly attribute HTMLCollection forms


readonly attribute HTMLCollection anchors


attribute HTMLElement body


这意味着在HTML文档里可以用
document.images
获得所有
<img>
元素,用
document.links
获取所有带有
href
属性的
<a>
元素,用
document.links
获取所有带有
name
属性的
<a>
元素,用
document.forms
获取所有
<form>
元素。另外获取
<body>
可以使用
document.body


自 HTML5(W3CWHATWG)开始还定义了
document.head
,删去了
document.anchors
,增加了获取
<embed>
document.embeds
和目前与之相同的
document.plugins
,以及获取
<script>
document.scripts


DOM 1 便在
Document
定义了
document.documentElement
来获取根元素并保留至今,在HTML文档里即
<html>
元素。

兼容性

IE 5.5 不支持
*
作为参数获取所有元素。IE6以上的IE以及各大浏览器均按照标准实现了
getElementsByTagName


虽然
document.scripts
document.embeds
document.plugins
直到HTML5才标准化,不过各版本IE和其他浏览器的现行版本都支持

document.head
需要IE9+才支持。其他DOM Tree Accessor基本在各版本IE和现行的浏览器里都有支持。

Webkit 代码分析

类似
getElementsByName
getElementsByTagName
ContainerNode
里实现。由于标准里对XML的特殊规定,这里会依据文档类型,换用
TagNodeList
或者
HTMLTagNodeList
作为
NodeListsNodeData::addCacheWithAtomicName<>
的template specialization(参见WebCore/dom/ContainerNode.cpp)。

TagNodeList
实现的
elementMatches
是:

if (m_localName != starAtom && m_localName != element.localName())
return false;
return m_namespaceURI == starAtom || m_namespaceURI == element.namespaceURI();


这里
starAtom
就是标准里说的
*
。先比对localName是否相符或为
*
,然后比对namespaceURI是否相符或为
*
。由于没有大小写转换步骤,所以遵循标准,是大小写敏感的。注意这里比对namespaceURI的步骤相对于
getElementsByTagName
是多余的,之所以加上是因为
getElementsByTagNameNS
也用
TagNodeList
,这样就可以偷懒不用再多写一个比对namespaceURI的版本。不过
getElementsByTagNameNS
用的其实是
addCacheWithQualifiedName
而不是
addCacheWithAtomicName
,其实
addCacheWithQualifiedName
addCacheWithAtomicName
的不同也就是它拿
TagNodeList
直接提前做好了template specification而已(参见WebCore/dom/NodeRareData.h

HTMLTagNodeList
实现的
elementMatches
是:

if (m_localName == starAtom)
return true;
const AtomicString& localName = element.isHTMLElement() ? m_loweredLocalName : m_localName;
return localName == element.localName();


按照标准所说,如果被比对的元素是HTML namespace里的,转换为小写再比较。注意这里没有比对namespaceURI,毕竟
getElementsByTagNameNS
不用它(标准里没有指明
getElementsByTagNameNS
需要转换大小写,所以用
TagNodeList
那个大小写敏感的过滤足矣)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐