`

15、DOM&HTML DOM(一)

阅读更多
  • DOM接口(API)

核心接口

DOM是语言无关的API,这意味着它的实现并不与Java、JavaScript或者其他语言绑定。DOM定义了Node的接口以及组成DOM树(也称之为文档)各元素的Node子接口,组成树的各元素都是Node节点。下面这些都是Node的子接口(即各节点类型),它们是组成DOM树的核心接口

Document ——最顶层的节点,所有的其他节点都是附属于它的。  

DocumentType ——DTD引用(使用 <!DOCTYPE >语法)的对象表现形式,例如 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">。它不能包含子节点。
DocumentFragment ——可以像Document一样来保存其他节点。
Element ——表示起始标签和结束标签之间的内容,例如 <tag> </tag>或者 <tag/>。这是唯一可以同时包含属性和子节点的节点类型。
Attr ——代表一对属性名和属性值。这个节点类型不能包含子节点。
Text ——代表XML文档中的在起始标签和结束标签之间,或者CData Section内包含的普通文本。这个节点类型不能包含子节点。
CDataSection —— <![CDATA[ ]]>的对象表现形式。这个节点类型仅能包含文本节点Text作为子节点。
Entity ——表示在DTD中的一个实体定义,例如 <!ENTITY foo "foo">。这个节点类型不能包含子节点。
EntityReference ——代表一个实体引用,例如&quot;。这个节点类型不能包含子节点。
ProcessingInstruction ——代表一个PI(处理指令)。这个节点类型不能包含子节点。
Comment ——代表XML注释。这个节点类型不能包含子节点。
Notation ——代表在DTD中定义的记号。这个很少用到。  

 

节点类型常量

Node接口定义了对应不同节点类型的12常量 (Node . nodeType),不同的节点对应不同的节点类型:
Node.ELEMENT_NODE (1)
Node.ATTRIBUTE_NODE (2)
Node.TEXT_NODE (3)
Node.CDATA_SECTION_NODE (4)
Node.ENTITY_REFERENCE_NODE (5)
Node.ENTITY_NODE (6)
Node.PROCESSING_INSTRUCTION_NODE (7)
Node.COMMENT_NODE (8)
Node.DOCUMENT_NODE (9)
Node.DOCUMENT_TYPE_NODE (10)
Node.DOCUMENT_FRAGMENT_NODE (11)
Node.NOTATION_NODE (12)

 

Node接口

Node接口也定义了一些所有节点类型都包含的属性和方法 ,下面的表格中列出了这些属性和方法:   

属性 / 方法

返回类型

   

nodeName

String

节点的名字;根据节点的类型而定义

nodeValue

String

节点的值;根据节点的类型而定义

nodeType

Number

节点的类型常量值之一

ownerDocument

Document

指向这个节点所属的文档

firstChild

Node

指向在 childNodes 列表中的第一个节点

lastChild

Node

指向在 childNodes 列表中的最后一个节点

childNodes

NodeList

所有子节点的列表

previousSibling

Node

指向前一个兄弟节点;如果这个节点就是第一个兄弟节点,那么该值为 null

nextSibling

Node

指向后一个兄弟节点;如果这个节点就是最后一个兄弟节点,那么该值为 null

hasChildNodes()

Boolean

childNodes 包含一个或多个节点时,返回真

attributes

NamedNodeMap

包含了代表一个元素的 属性 Attr 对象;仅用于 Element 节点

appendChild(node )

Node

node 添加到 childNodes 的末尾

removeChild(node )

Node

childNodes 中删除 node

replaceChild(newnode , oldnode )

Node

childNodes 中的 oldnode 替换成 newnode

insertBefore(newnode , refnode )

Node

childNodes 中的 refnode 之前插入 newnode

 

除节点外, DOM 还定义了一些助手对象,它们可以和节点一起使用,但不是 DOM 文档必有的部分。

 

NodeList ——节点数组,按照数值进行索引;用来表示一个元素的子节点。

NamedNodeMap ——同时用数值和名字进行索引的节点表;用于表示元素属性。   

 

这些助手对象为处理 DOM 文档提供附加的访问和遍历方法。

Document接口

Document 对象的属性

属性 描述 IE F O W3C
async 规定 XML 文件的下载是否应当被同步处理。 5 1.5 9 No
childNodes 返回属于文档的子节点的节点列表。 5 1 9 Yes
doctype 返回与文档相关的文档类型声明 (DTD)。 6 1 9 Yes
documentElement 返回文档的根节点 5 1 9 Yes
documentURI 设置或返回文档的位置 No 1 9 Yes
domConfig 返回normalizeDocument()被调用时所使用的配置 No Yes
firstChild 返回文档的首个子节点 5 1 9 Yes
implementation 返回处理该文档的 DOMImplementation 对象。 No 1 9 Yes
inputEncoding 返回用于文档的编码方式(在解析时)。 No 1 No Yes
lastChild 返回文档的最后一个子节点。 5 1 9 Yes
nodeName 依据节点的类型返回其名称。 5 1 9 Yes
nodeType 返回节点的节点类型。 5 1 9 Yes
nodeValue 根据节点的类型来设置或返回节点的值。 5 1 9 Yes
strictErrorChecking 设置或返回是否强制进行错误检查。 No 1 No Yes
text 返回节点及其后代的文本(仅用于 IE)。 5 No No No
xml 返回节点及其后代的 XML(仅用于 IE)。 5 No No No
xmlEncoding 返回文档的编码方法。 No 1 No Yes
xmlStandalone 设置或返回文档是否为 standalone。 No 1 No Yes
xmlVersion 设置或返回文档的 XML 版本。 No 1 No Yes

 

Document 对象的方法

属性 描述 IE F O W3C
adoptNode(sourcenode) 从另一个文档向本文档选定一个节点,然后返回被选节点。 No Yes
createAttribute(name) 创建拥有指定名称的属性节点,并返回新的 Attr 对象。 6 1 9 Yes
createAttributeNS(uri,name) 创建拥有指定名称和命名空间的属性节点,并返回新的 Attr 对象。 9 Yes
createCDATASection() 创建 CDATA 区段节点。 5 1 9 Yes
createComment() 创建注释节点。 6 1 9 Yes
createDocumentFragment() 创建空的 DocumentFragment 对象,并返回此对象。 5 1 9 Yes
createElement() 创建元素节点。 5 1 9 Yes
createElementNS() 创建带有指定命名空间的元素节点。 No 1 9 Yes
createEvent() 创建新的 Event 对象。 Yes
createEntityReference(name) 创建 EntityReference 对象,并返回此对象。 5 No Yes
createExpression() 创建一个XPath表达式以供稍后计算。 Yes
createProcessingInstruction(target,data) 创建 ProcessingInstruction 对象,并返回此对象。 5 9 Yes
createRange() 创建 Range 对象,并返回此对象。 No Yes
evaluate() 计算一个 XPath 表达式。 No 1 9 Yes
createTextNode() 创建文本节点。 5 1 9 Yes
getElementById() 查找具有指定的唯一 ID 的元素。 5 1 9 Yes
getElementsByTagName() 返回所有具有指定名称的元素节点。 5 1 9 Yes
getElementsByTagNameNS() 返回所有具有指定名称和命名空间的元素节点。 No 1 9 Yes
importNode() 把一个节点从另一个文档复制到该文档以便应用。 9 Yes
loadXML() 通过解析XML标签字符串来组成文档。
normalizeDocument() No Yes
renameNode() 重命名元素或者属性节点。 No Yes

 

Node的名、值、属性

nodeName nodeValue attributes 的值将根据以下节点类型的不同而不同:       

 

 Interface

nodeName

nodeValue

attributes

Attr

Attr.name 相同

Attr.value 相同

null

CDATASection

"#cdata-section"

CharacterData.data 相同,CDATA 节的内容

null

Comment

"#comment"

CharacterData.data 相同,该注释的内容

null

Document

"#document"

null

null

DocumentFragment

"#document-fragment"

null

null

DocumentType

DocumentType.name 相同

null

null

Element

Element.tagName 相同

null

NamedNodeMap

Entity

entity name

null

null

EntityReference

引用的实体名称

null

null

Notation

notation name

null

null

ProcessingInstruction

ProcessingInstruction.target 相同

ProcessingInstruction.data 相同

null

Text

"#text"

CharacterData.data 相同,该文本节点的

 

    IE与Mozilla上的childNodes区别

    如同對於標準 HTML,對於可各方面控制 XML 檔的 DOM 的支援,Mozilla 也是依 W3C 所定的 XML DOM 規格。Mozilla 與 Internet Explorer 在 XML DOM 上的不同處大多在於 Internet Explorer 非標準的處理方式 。一個常見的差異是對空白字元節點的處理。 通常在建立 XML 時,XML 節點間會有空白。 Internet Explorer 用 XMLNode.childNodes[] 時不會包括這些空白節點,但在 Mozilla 上這些節點會在 array 裡

     

    XML: 
      <?xml version="1.0"?> 
      <myXMLdoc xmlns:myns="http://myfoo.com"> 
        <myns:foo>bar</myns:foo> 
      </myXMLdoc>
    
    JavaScript:
      var myXMLDoc = getXMLDocument().documentElement; 
      alert(myXMLDoc.childNodes.length); 
    

    The first line of JavaScript 的第一行載入 XML 檔並用 documentElement 來存取它的 root 元素 (myXMLDoc,getXMLDocument()为XML DOM类型,即文档类型,是一个自定义方法 )。第二行顯示子節點的數目。根據 W3C 規格,接在一起的空白與換行字符組成一個文字節點 。在 Mozilla 上 myXMLdoc 節點有三個子:一個有換行字符與兩個空白的文字節點、myns:foo 節點、與另一個有換行字符的文字節點 。Internet Explorer 並不遵循這個,因此上面的程式碼會顯示 "1",表示只有 myns:foo 節點 。所以,如要迴走(遍历、迭代的意思)子節點並掠過文字節點,要分辨這些節點。

     

    如前所述,每个节点都有一个节点类型属性代表节点类型。例如,一个元素节点有类型1,而文档节点类型9。忽略文本节点,你必须检查类型3(文本节点)和8(注释节点),像这样:

    XML:
      <?xml version="1.0"?>   
      <myXMLdoc xmlns:myns="http://myfoo.com"> 
        <myns:foo>bar</myns:foo> 
      </myXMLdoc>
    
    JavaScript: 
      var myXMLDoc = getXMLDocument().documentElement; 
      var myChildren = myXMLDoc.childNodes; 
    
      for (var run = 0; run < myChildren.length; run++){ 
        if ( (myChildren[run].nodeType != 3) &&
              myChildren[run].nodeType != 8) ){ 
          // not a text or comment node 
        }
      }
    

     

    另:特别要注意的是,Mozilla上存在此种情况是因为某节点下的子节点即含有文本 (TEXT)节点(一般是元素前有回车符、TAB键、空格,或其他可打印字符),又含有元素(ELEMENT)节点时childNodes才把空白字符也 算作节点。但如果某节点下只有文本时(没有其他ELEMENT元素节点),此时的childNodes只会有一个节点(即一个文本节点),详细请看下一节 内容。

    IE上的nodeValue与text区别

    在IE上文本节点除了有nodeValue属性外还有一个text属性,作用都是返回文本的值,但两者区别在于:nodeValue返回的数据会包含文本节点前后的空白字符,包含回车符,但text就只返回文本本身,不包含前后空白字符。

    <root>
    	 data
    </root>

     

    <script type="text/javascript" src="detect.js"></script>
    <script type="text/javascript" src="xmldom.js"></script>
    <script type="text/javascript">
    
    var oXmlDom = new XmlDom();
    oXmlDom.onreadystatechange = function () {
    	if (oXmlDom.readyState == 4 || (oXmlDom.getReadyState && oXmlDom.getReadyState() == 4)) {
    		var nodeList = oXmlDom.documentElement.childNodes;
    		alert(nodeList.length);//IE与Mozilla上都是 1 
    		for(var i = 0 ; i < nodeList.length; i++){
    			
    			alert('nodeValue.length = ' + nodeList[i].nodeValue.length 
    			+ '-->' + nodeList[i].nodeValue + '<--');
    			
    			//Mozilla上没有text属性,所以不会输出
    			if(nodeList[i].text){
    					alert('text.length = ' + nodeList[i].text.length 
    					+ '-->' + nodeList[i].text + '<--');
    			}
    		
    			
    		}			
    	}
    };
    oXmlDom.load("test.xml");
    </script>

     

    IE上结果如下:
       

    注:text不会返回子节点的文本内容

     

    Mozilla上结果如下(注:Mozilla无text属性,所以不输出):


    • 利用 HTML DOM HTML 元素之间导航

    可以使用document的documentElement属性来得到HTML文档的根节点:

    var oHtml = document.documentElement; 

     
    如果想继续得到 <head/>与 <body/>元素时,可以这样实现:

    var oHead = oHtml.firstChild; 
    var oBody = oHtml.lastChild; 

     
    也可以使用childNodes属性来完成同样的工作:

    var oHead = oHtml.childNodes[0]; 
    var oBody = oHtml.childNodes[1]; 

     
    你还可以通过使用childNodes.length属性来获取子节点的数量:

    oHtml.childNodes.length;//2 

     
    注意:方括号标记其实是NodeList在JavaScript中的简便实现。实际上正式的从childNodes列表中获取子节点的方法是使用item()方法

    var oHead = oHtml.childNodes.item(0); 
    var oBody = oHtml.childNodes.item(1);

     
    HTML DOM页定义了document.body作为指向 <body/>元素的指针:

    var oBody = document.body; 

     
    测试oHtml、oHead和oBody这三个元素之间的关系:

    alert(oHead.parentNode == oHtml);//true 
    alert(oBody.parentNode == oHtml); //true 
    alert(oBody.previousSibling == oHead); //true 
    alert(oHead.nextSibling == oBody); //true 
    alert(oHead.ownerDocument == document); //true

     

    • 检测 HTML DOM 节点类型

    我们可以通过使用nodeType属性检验节点类型:

    alert(document.nodeType); //9 
    alert(document.documentElement.nodeType);//1 

     
    也可以用Node常量来匹配这些值:

    alert(document.nodeType == Node.DOCUMENT_NODE); //true 
    alert(document.documentElement.nodeType == Node.ELEMENT_NODE);//true

     

    这段代码可以在Mozilla 1.0+、Opera 7.0+和Safari 1.0+上正常运行。不幸的是,IE不支持这些常量,所以这些代码在IE上会产生错误。所幸,可以通过定义匹配节点类型的常量来纠正这种情况,正如下面这样:

     

    if (typeof Node == "undefined") {
    	var Node = {ELEMENT_NODE:1,
    		 //...
    		NOTATION_NODE:12
    	};
    }
    • 处理 Element 元素的属性

    Node接口已具有attributes属性,且已被所有类型的节点继承,然而,只有Element节点才能有属性。Element节点的attributes属性其实是NamedNodeMap,它提供一些用于访问和处理其内容的方法: 

    getNamedItem (name )——返回nodeName属性值等于name的Attr节点;
    remove NamedItem (name )——删除nodeName属性值等于name的Attr节点;
    setNamedItem (node )——将node添加到列表中,按其nodeName属性进行索引;
    item (pos )——像NodeList一样,返回在位置pos的Attr节点;


    NamedNodeMap 对象也有一个length属性来指示它所包含的属性个数。

    NamedNodeMap中存储的为Attr节点,Attr的nodeName属性被设置为元素属性名称,而nodeValue属性被设置为元素属性的值。例如,假设有这样一个元素:

    <p style='color:red' id='p1'>Hello world! </p> 

     

    同时,假设变量oP包含指向这个元素的一个引用。于是可以这样访问id属性的值:

    var sId = oP.attributes.getNamedItem('id').nodeValue; 

     

    当然,还可以用数值方式访问id属性:

    var sId = oP.attributes.item(1).nodeValue; 

     

    还可以通过给nodeValue属性赋新值来改变id属性:

    oP.attributes.getNamedItem('id').nodeValue = 'newId'; 

     

    Attr节点也有一个完全等同于(同时也完全同步于)nodeValue属性的value属性,并且有name属性和nodeName属性保持同步 。我们可以随意使用这些属性来修改或变更属性。

    因为这个方法有些累赘,DOM又定义了三个Element元素方法来帮助访问其属性:
    getAttribute (name )——等于attributes.getNamedItem(name).value
    setAttribute (name, newvalue )——等于attribute.getNamedItem(name).value = newvalue
    removeAttribute (name )——等于attributes.removeNamedItem(name)

     

    这些方法相当有用,可以直接处理属性值,完全地隐藏Attr节点。所以,要获取前面用的 <p/>的id属性,只需这样做:

    var sId = oP.getAttribute("id"); 

     

    同时要更改ID,可以这样做

    op.setAttribute('id','newId'); 

     

    正如你所看到的,这些方法要比使用NamedNodeMap的方法简洁得多。

    • 访问指定节点

    如何访问父节点和子节点前面已讲过了,都很简单,但是如果想访问文档中位置很深的某个节点 (或者一组节点),要怎么做呢?

    1、getElementsByTagName()

    核心(XML核心DOM的属性和方法是通用的)DOM定义了getElementsByTagName()方法,用来返回一个包含所有的tagName(标签名)等于某个指定值的元素的NodeList。下一行代码返回文档中所有 <img/>元素的列表:

    var oImgs = document.getElementsByTagName("img"); 

     

    访问第一个 <img/>元素:

    alert(oImgs.item(0).tagName);//IMG 

     

    注:大部分浏览器按照大写来记录标签名,即使XHTML约定指出标签名应当全部小写

    但是假如你只想获取在某个页面第一个段落中的所有图像呢?可以通过对第一个段落元素调用getElementsByTagName()来完成,像这样:

    var oPs = document.getElementsByTagname('p'); 
    var oImgsInP = oPs[0].getElementsByTagName('img');  

     
    这样就限制元素的搜索范围。

     

    返回文档中所有元素:

    var oAllElements = document.getElementsByTagname('*');

     
    注:IE不支持,使用document.all

    2. getElementsByName()

    HTML DOM定义了getElementsByName(),它用来获取所有HTML标签中的name属性等于指定值元素的NodeList。该方法只适用于HTML文档,不是核心(XML)DOM所定义的。
    注:IE 6.0和Opera 7.5在这个方法的使用上还存在一些错误。首先,除了返回name属性等于指定值的元素,它们还会返回id等于指定值的元素。第二,它们仅仅检查 <input/>和 <img/>元素。

    3. getElementById()

    这是HTML DOM定义的第二种方法,它将返回id 属性等于指定值的元素。在HTML中,id 属性是唯一的。
    注:如果给定的ID匹配某个元素的name属性,且是每个,IE 6.0会返回这个元素。这是一个bug,使用时必须非常小心的一个问题。

    • 大小: 4.5 KB
    • 大小: 4.4 KB
    • 大小: 4.7 KB
    分享到:
    评论

    相关推荐

    Global site tag (gtag.js) - Google Analytics