DOM 即(Document Object Model),文档对象模型,DOM实际是把HTML当作XML文件来进行处理,用对象的眼光来打量HTML,可以说DOM是继HTML后Web的最有用的发明。
Some review of XML
SGML(基于标签的语言的普遍规范),在SGML被用于定义HTML的DTD时,发现HTML本身是很不规范的。主要表现在某些标签可以省略/没 有/不允许结束标签(</xxx>),标签互相嵌入而很不不规范,属性值的定义方法也不统一等等。所以XML出现了,HTML中不规范的地方 都被明确定义,注意的是XML定义的是一种语言的语法和规范,是一系列满足这种规范的语言的统称,具体不同的场合会有不同的具体实现定义不同的标签及属性 来来解决不同的问题,如RDF,RSS,SOAP,XSLT,XSL等等,当然HTML的XML实现为XHTML。XML的实质含义是使用结构化的纯文本 来表达数据。
XML几个语法要点:
首行为XML prolog,一般为<?xml version=”1.0”?>,该行告诉xml praser/浏览器,该XML如何被prase。
然后是文档类型声明(DTD),例如<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
然后是document element,它必须把所有其他标签都括入其中。就是该XML的最外层标签。也就是Root Element,注意这个要与DTD中声明的root element type相一致,如上面的html。
不想被Praser解析的东西用<![CDATA[ ]]>括起来。
在document element中间的用<? … ?>括起来的语句被称为PI(processing instruction),作用是给praser一些更特定的信息。
XML的API:
SAX(Sample API for XML):第一个,Java语言实现,event-based,praser从上到下的解析XML文档,当遇到每个标签/属性/值…时就会激发事件,而具体在该事件做什么由程序员定义。
优点,lightweight,fast,缺点,任何时候,你想停下,回退,或专门指定解析该文档的某特定部分时,都得从头从文档的第一行开始解析。
DOM:基于树结构,并且当解析完后,你想访问或修改添加文档对象都不需要重新解析。DOM是不针对于语言的,浏览器负责对DOM实现进行JavaScript的支持。
—————————————————————————————————————————
DOM的核心: Node
由于DOM是树形结构,所以一个节点被抽象为对象Node,这是DOM的核心对象:
Node的种类一共有12种,通过Node.nodeType的取值来确定(为1-12),分为:
❑ Node.ELEMENT_NODE (1)
❑ Node.ATTRIBUTE_NODE (2)
❑ Node.TEXT_NODE (3) :<![CDATA[ ]]>中括着的纯文本,他没有子节点
❑ Node.CDATA_SECTION_NODE (4) :子节点一定为TextNode
❑ Node.ENTITY_REFERENCE_NODE (5) :
❑ Node.ENTITY_NODE (6) :DTD中的实体定义<!ENTITY foo “foo”>,无子节点
❑ Node.PROCESSING_INSTRUCTION_NODE (7) :PI,无子节点
❑ Node.COMMENT_NODE (8)
❑ Node.DOCUMENT_NODE (9) :最外层的Root element,包括所有其它节点
❑ Node.DOCUMENT_TYPE_NODE (10) :DTD,<!DOCTYPE………..>
❑ Node.DOCUMENT_FRAGMENT_NODE (11)
❑ Node.NOTATION_NODE (12) :DTD中的Nation定义
Node的属性和方法
nodeName 返回String. The name of ths node;this is defined depending on theype of node.
nodeValue 返回String. The value of the node'this is defined depending on the type of node.
nodeType 返回Number. One of the node type constant values.
ownerDocument 返回Document. Pointer to the document that this node belongs to.
firstChild 返回Node. Pointer to the first node in the childNodes list.
lastChild 返回Node. Pointer to the last node in the childNodes list.
childNodes 返回NodeList. A list of all child nodes.
previousSibling 返回Node. Pointer to the previous sibling;null if this is the first sibling.
nextSibling 返回Node. Pointer to the next sibling;null if this is the last sibling.
attributes 返回NamedNodeMap. Contains Attr objects respresenting an element's attributes;only used for Element nodes.
appendChild(node) 返回Node. Adds node to the end of childNodes.
hasChildNodes() 返回Boolean. Returns true when childNodes contains one or more nodes.
removeChild(node) 返回Node. Removes node from childNodes.
replaceChild(newnode, oldnode) 返回Node. Replace oldnode in childNodes with newnode.
insertBefore(newnode, refnode) 返回Node. Inserts newnode before refnode in childNodes.
—————————————————————————————————————————
DOM的使用
DOM是分级别的,不同浏览器对DOM支持的级别不同。DOM level1 (core,用来解析XML-base的文档,和DOM HTML,用来针对HTML,因为DOM并非只针对HTML的),DOM Level2(event,以前都是通过DHTML支持,style,与CSS沟通,等等。。)DOM level3(DOM Load and Save;DOM Validation;对XML1.0的支持,包括:XML Infoset, XPath,XML Base)
Netscape Navigator 1.0-4.x DOM兼容性(-)
Netscape 6.0+(Mozilla 0.6.0+) DOM兼容性(Level 1, Level 2, Level 3 (partial))
Internet Explorer 2.0-4.x DOM兼容性(-)
Internet Explorer 5.0 DOM兼容性(Level 1 (minimal))
Internet Explorer 5.5+ DOM兼容性(Level 1 (almost all))
Opera 1.0-6.0 DOM兼容性(-)
Opera 7.0+ DOM兼容性(Level 1 (almost all), Level 2 (partial))
Safari 1.0+ / Konqueror~2.0+ DOM兼容性(Level 1)
获得Node:
/* 通过document对象 */
var oHtml = document.documentElement;
/* 得到<head />和<body /> */
var oHead = oHtml.firstChild;
var oBody = oHtml.lastChild;
/* 可以用这种方式 */
var oHead = oHtml.childNodes[0];
var oBody = oHtml.childNodes[1];
/* 也可以使用方法获取数组的索引值 */
var oHead = oHtml.childNodes.item(0);
var oBody = oHtml.childNodes.item(1);
/* 使用document.body来得到<body /> */
var oBody = document.body;
使用Attributes值:Node接口的attributes()方法返回一个NamedNodeMap,从它可以得到具体的Attribute并加以操作。或者是有Node接口本身的getAttribute()方法来直接得到Attribute。
/* 使用Node的attribute的getNamedItem()方法 */
var sId = oP.attributes.getNamedItem("id").nodeValue;
/* 或者使用item()方法 */
var sId = oP.attributes.item(1).nodeValue;
/* 或者直接使用Node的getAttribute()获取Id */
var sId = oP.getAttribute("id");
得到指定的Node:使用getElementsByTagName()
/* 得到<img />Elements */
var oImgs = document.getElementsByTagName("img");
/* 得到第一段里所有的<img /> */
var oPs = document.getElementsByTagName("p");
var oImgsInP = oPs[0].getElementsByTagName("img");
还有getElementsByName(),getElementsById();
/* 得到id为"div1"的<div> */
var oDivs = document.getElementsByTagName("div");
var oDiv1 = null;
for(var i=0; i<oDivs.length; i++){
if(oDivs[i].getAttribute("id") == "div1"){
oDiv1 = oDivs[i];break;
}
}
/* 使用document.getElementById() */
var oDiv1 = document.getElementById("div1");
生成与操作Node
createAttribute(name) :创建一个名为name的属性节点。IE,Mozilla,opera支持,Safari不支持。
createCDATASection(text) :创建一个子节点为text的CDATA区。Mozilla支持,IE,Opera,Safari不支持。
createComment(text) :创建一个注释内容为text的注释节点。各浏览器均支持。
createDocumentFragment() :创建一个文档片断(fragment)节点。各浏览器均支持。
createElement(tagName) :创建一个名为tagName的元素节点。各浏览器均支持。
createEntityReference(name) :Creates an entity reference node with the given name。Mozilla 支持。IE,Opera,Safari不支持。
createProcessingInstruction(target, data) :Creates a PI node with the given target and data。 Mozilla 支持。IE,Opera,Safari不支持。
createTextNode(text) :创建一个包含text的文本节点。各浏览器均支持。
观察可知最普遍的,最重要的方法是createElement(),createDocumentFragment(), create TextNode()。
/*使用createElement(),createTextNode(),appendChild()动态添加节点*/
function createMessage(){
var op = document.createElement("p");
var oText = document.createTextNode("hello world!");
op.appendChild(oText);
document.body.appendChild(op);
}
使用removeChild(), replaceChild(), and insertBefore()
/* remove 节点 */
function removeMessage(){
var op = document.body.getElementsByTagName('p')[0];
op.parentNode.removeChild(op);
}
/* replace 节点 */
function insertMessage(){
var oNewP = document.createElement('p');
var oText = document.createTextNode('hello csser!');
oNewP.appendChild(oText);
var oOldP = document.getElementsByTagName('p')[0];
document.body.insertBefore(oNewP, oOldP);
}
使用createDocumentFragment()
/* 通常做法 */
var arrText = ['first', 'second', 'third'];
for(var i=0; i<arrText.length; i++){
var op = document.createElement('p');
var oText = document.createTextNode(arrText[i]);
op.appendChild(oText);
document.body.appendChild(op);
}
/* 使用documentFragment */
var arrText = ['first', 'second', 'third'];
var oFragment = document.createDocumentFragment();
for(var i=0; i<arrText.length; i++){
var op = document.createElement('p');
var oText = document.createTextNode(arrText[i]);
op.appendChild(oText);
oFragment.appendChild(op);
}
document.body.appendChild(oFragment);
CSSER注:上面的比较能看出,通过DocumentFragment的方式能提高效率。
—————————————————————————————————————————
HTML DOM:
使用DOM的核心方法是针对所有XML的,针对HTML DOM有特殊的方法,如
使用DOM core:oImg.setAttribute(“src”, “mypicture2.jpg”);
使用HTML DOM:oImg.src = “mypicture2.jpg”;