<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 73,  comments - 55,  trackbacks - 0
    < script?language = " JavaScript " >
    <!--
    var ?doc? = ? new ?ActiveXObject( " Msxml2.DOMDocument " );? // ie5.5+,CreateObject("Microsoft.XMLDOM")?


    // 加載文檔
    //
    doc.load("b.xml");

    // 創建文件頭
    var ?p? = ?doc.createProcessingInstruction( " xml " , " version='1.0'??encoding='gb2312' " );

    ????
    // 添加文件頭

    ????doc.appendChild(p);

    // 用于直接加載時獲得根接點

    //
    var?root?=?doc.documentElement;

    // 兩種方式創建根接點
    //
    ????var?root?=?doc.createElement("students");
    ???? var ?root? = ?doc.createNode( 1 , " students " , "" );

    ????
    // 創建子接點

    ???? var ?n? = ?doc.createNode( 1 , " ttyp " , "" );

    ????????
    // 指定子接點文本

    ???????? // n.text?=?"?this?is?a?test";
    ????
    ????
    // 創建孫接點

    ???? var ?o? = ?doc.createElement( " sex " );
    ????????o.text?
    = ? " " ;???? // 指定其文本


    ????
    // 創建屬性
    ???? var ?r? = ?doc.createAttribute( " id " );
    ????????r.value
    = " test "
    ;

    ????????
    // 添加屬性

    ????????n.setAttributeNode(r);

    ????
    // 創建第二個屬性????

    ???? var ?r1? = ?doc.createAttribute( " class " );
    ????????r1.value
    = " tt "
    ;
    ????????
    ????????
    // 添加屬性

    ????????n.setAttributeNode(r1);

    ????????
    // 刪除第二個屬性

    ????????n.removeAttribute( " class " );

    ????????
    // 添加孫接點

    ????????n.appendChild(o);

    ????????
    // 添加文本接點

    ????????n.appendChild(doc.createTextNode( " this?is?a?text?node. " ));

    ????????
    // 添加注釋

    ????????n.appendChild(doc.createComment( " this?is?a?comment\n " ));
    ????
    ????????
    // 添加子接點

    ????????root.appendChild(n);
    ????
    ????
    // 復制接點

    ???? var ?m? = ?n.cloneNode( true );

    ????????root.appendChild(m);
    ????????
    ????????
    // 刪除接點

    ????????root.removeChild(root.childNodes( 0 ));

    ????
    // 創建數據段

    ???? var ?c? = ?doc.createCDATASection( " this?is?a?cdata " );
    ????????c.text?
    = ? " hi,cdata "
    ;
    ????????
    // 添加數據段

    ????????root.appendChild(c);
    ????
    ????
    // 添加根接點

    ????doc.appendChild(root);

    ????
    // 查找接點

    ???? var ?a? = ?doc.getElementsByTagName( " ttyp " );
    ????
    // var?a?=?doc.selectNodes("http://ttyp");


    ????
    // 顯示改接點的屬性
    ???? for ( var ?i = ? 0 ;i < a.length;i ++ )
    ????
    {
    ????????alert(a[i].xml);
    ????????
    for ( var ?j = 0 ;j < a[i].attributes.length;j ++
    )
    ????????
    {
    ????????????alert(a[i].attributes[j].name);
    ????????}

    ????}


    ????
    // 修改節點,利用XPATH定位節點
    ???? var ?b? = ?doc.selectSingleNode( " //ttyp/sex " );
    ????b.text?
    = ? " "
    ;

    ????
    // alert(doc.xml);


    ????
    // XML保存(需要在服務端,客戶端用FSO)
    ???? // doc.save();
    ????
    ????
    // 查看根接點XML

    ???? if (n)
    ????
    {
    ????????alert(n.ownerDocument.xml);
    ????}


    // -->
    </ script >


    ??? 在
    DOM 眼中, HTML XML 一樣是一種樹形結構的文檔, <html> 是根( root )節點, <head> <title > <body> <html> 的子( children )節點,互相之間是兄弟( sibling )節點; <body> 下面才是子節點 <table> <span> <p> 等等。如下圖:
    HTML文檔結構.jpg
    ??? 這個是不是跟
    XML 的結構有點相似呢。不同的是, HTML 文檔的樹形主要包含表示元素、標記的節點和表示文本串的節點。


    ?HTML
    文檔的節點

    DOM 下, HTML 文檔各個節點被視為各種類型的 Node 對象。每個 Node 對象都有自己的屬性和方法,利用這些屬性和方法可以遍歷整個文檔樹。由于 HTML 文檔的復雜性, DOM 定義了 nodeType 來表示節點的類型。這里列出 Node 常用的幾種節點類型:

    接口

    nodeType 常量

    nodeType

    備注

    Element

    Node.ELEMENT_NODE

    1

    元素節點

    Text

    Node.TEXT_NODE

    3

    文本節點

    Document

    Node.DOCUMENT_NODE

    9

    document

    Comment

    Node.COMMENT_NODE

    8

    注釋的文本

    DocumentFragment

    Node.DOCUMENT_FRAGMENT_NODE

    11

    document 片斷

    Attr

    Node.ATTRIBUTE_NODE

    2

    節點屬性

    DOM 樹的根節點是個 Document 對象,該對象的 documentElement 屬性引用表示文檔根元素的 Element 對象(對于 HTML 文檔,這個就是 <html> 標記)。 Javascript 操作 HTML 文檔的時候, document 即指向整個文檔, <body> <table> 等節點類型即為 Element Comment 類型的節點則是指文檔的注釋。具體節點類型的含義,請參考《 Javascript 權威指南》,在此不贅述。

    Document 定義的方法大多數是生產型方法,主要用于創建可以插入文檔中的各種類型的節點。常用的 Document 方法有:

    方法

    描述

    createAttribute()

    用指定的名字創建新的 Attr 節點。

    createComment()

    用指定的字符串創建新的 Comment 節點。

    createElement()

    用指定的標記名創建新的 Element 節點。

    createTextNode()

    用指定的文本創建新的 TextNode 節點。

    getElementById()

    返回文檔中具有指定 id 屬性的 Element 節點。

    getElementsByTagName()

    返回文檔中具有指定標記名的所有 Element 節點。

    對于 Element 節點,可以通過調用 getAttribute() setAttribute() removeAttribute() 方法來查詢、設置或者刪除一個 Element 節點的性質,比如 <table> 標記的 border 屬性。下面列出 Element 常用的屬性:

    屬性

    描述

    tagName

    元素的標記名稱,比如 <p> 元素為 P HTML 文檔返回的 tabName 均為大寫。

    Element 常用的方法:

    方法

    描述

    getAttribute()

    以字符串形式返回指定屬性的值。

    getAttributeNode()

    Attr 節點的形式返回指定屬性的值。

    getElementsByTabName()

    返回一個 Node 數組,包含具有指定標記名的所有 Element 節點的子孫節點,其順序為在文檔中出現的順序。

    hasAttribute()

    如果該元素具有指定名字的屬性,則返回 true

    removeAttribute()

    從元素中刪除指定的屬性。

    removeAttributeNode()

    從元素的屬性列表中刪除指定的 Attr 節點。

    setAttribute()

    把指定的屬性設置為指定的字符串值,如果該屬性不存在則添加一個新屬性。

    setAttributeNode()

    把指定的 Attr 節點添加到該元素的屬性列表中。

    Attr 對象代表文檔元素的屬性,有 name value 等屬性,可以通過 Node 接口的 attributes 屬性或者調用 Element 接口的 getAttributeNode() 方法來獲取。不過,在大多數情況下,使用 Element 元素屬性的最簡單方法是 getAttribute() setAttribute() 兩個方法,而不是 Attr 對象。


    使用
    DOM 操作 HTML 文檔

    Node 對象定義了一系列屬性和方法,來方便遍歷整個文檔。用 parentNode 屬性和 childNodes[] 數組可以在文檔樹中上下移動;通過遍歷 childNodes[] 數組或者使用 firstChild nextSibling 屬性進行循環操作,也可以使用 lastChild previousSibling 進行逆向循環操作,也可以枚舉指定節點的子節點。而調用 appendChild() insertBefore() removeChild() replaceChild() 方法可以改變一個節點的子節點從而改變文檔樹。

    需要指出的是, childNodes[] 的值實際上是一個 NodeList 對象。因此,可以通過遍歷 childNodes[] 數組的每個元素,來枚舉一個給定節點的所有子節點;通過遞歸,可以枚舉樹中的所有節點。下表列出了 Node 對象的一些常用屬性和方法:

    Node 對象常用屬性:

    屬性

    描述

    attributes

    如果該節點是一個 Element ,則以 NamedNodeMap 形式返回該元素的屬性。

    childNodes

    Node[] 的形式存放當前節點的子節點。如果沒有子節點,則返回空數組。

    firstChild

    Node 的形式返回當前節點的第一個子節點。如果沒有子節點,則為 null

    lastChild

    Node 的形式返回當前節點的最后一個子節點。如果沒有子節點,則為 null

    nextSibling

    Node 的形式返回當前節點的兄弟下一個節點。如果沒有這樣的節點,則返回 null

    nodeName

    節點的名字, Element 節點則代表 Element 的標記名稱。

    nodeType

    代表節點的類型。

    parentNode

    Node 的形式返回當前節點的父節點。如果沒有父節點,則為 null

    previousSibling

    Node 的形式返回緊挨當前節點、位于它之前的兄弟節點。如果沒有這樣的節點,則返回 null

    Node 對象常用方法:

    方法

    描述

    appendChild()

    通過把一個節點增加到當前節點的 childNodes[] 組,給文檔樹增加節點。

    cloneNode()

    復制當前節點,或者復制當前節點以及它的所有子孫節點。

    hasChildNodes()

    如果當前節點擁有子節點,則將返回 true

    insertBefore()

    給文檔樹插入一個節點,位置在當前節點的指定子節點之前。如果該節點已經存在,則刪除之再插入到它的位置。

    removeChild()

    從文檔樹中刪除并返回指定的子節點。

    replaceChild()

    從文檔樹中刪除并返回指定的子節點,用另一個節點替換它。

    接下來,讓我們使用上述的 DOM 應用編程接口,來試著操作 HTML 文檔。

    A 、遍歷文檔的節點

    DOM 把一個 HTML 文檔視為樹,因此,遍歷整個樹是應該是家常便飯。跟之前說過的一樣,這里我們提供兩個遍歷樹的例子。通過它,我們能夠學會如何使用 childNodes[] firstChile lastChild nextSibling previousSibling 遍歷整棵樹。

    例子 1-- sample3_1.htm

    這個例子使用了 childNodes[] 和遞歸方式來遍歷整個文檔,統計文檔中出現的 Element 元素總數,并把 Element 標記名全部打印出來。需要特別注意的是,在使用 DOM 時,必須等文檔被裝載完畢再執行遍歷等行為操作文檔。 sample3_1.htm 具體代碼如下:

    <html>

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">

    <title> 無標題文檔 </title>

    <script language="javascript">

    var elementName = ""; // 全局變量,保存 Element 標記名,使用完畢要清空

    function countTotalElement(node) { // 參數 node 是一個 Node 對象

    ?????? var total = 0;

    ?????? if(node.nodeType == 1) { // 檢查 node 是否為 Element 對象

    ????????????? total++;???????????????? // 如果是,計數器加 1

    ????????????? elementName = elementName + node.tagName + "\r\n"; // 保存標記名

    ?????? }

    ?????? var childrens = node.childNodes;???????? // 獲取 node 的全部子節點

    ?????? for(var i=0;i<childrens.length;i++) {

    ????????????? total += countTotalElement(childrens[i]); // 在每個子節點上進行遞歸操作

    ?????? }

    ?????? return total;

    }

    </script>

    </head>

    <body>

    <a href="javascript:void(0)"

    onClick="alert(' 標記總數: ' + countTotalElement(document) + '\r\n 全部標記如下: \r\n' + elementName);elementName='';"> 開始統計 </a>

    </body>

    </html>

    運行效果如下:

    遍歷文檔_1.jpg 遍歷文檔_2.jpg???????????????

    例子 2 – sample3_2.htm

    接下來使用 firstChile lastChild nextSibling previousSibling 遍歷整個文檔樹。修改一下 countTotalElement 函數,其他跟 sample3_1.htm 一樣:

    function countTotalElement(node) { // 參數 node 是一個 Node 對象

    ?????? var total = 0;

    ?????? if(node.nodeType == 1) { // 檢查 node 是否為 Element 對象

    ????????????? total++;???????????????? // 如果是,計數器加 1

    ????????????? elementName = elementName + node.tagName + "\r\n"; // 保存標記名

    ?????? }

    ?????? var childrens = node.childNodes;???????? // 獲取 node 的全部子節點

    ?????? for(var m=node.firstChild; m!=null;m=m.nextSibling) {

    ????????????? total += countTotalElement(m); // 在每個子節點上進行遞歸操作

    ?????? }

    ?????? return total;

    }

    B 、搜索文檔中特定的元素

    在使用 DOM 的過程中,有時候需要定位到文檔中的某個特定節點,或者具有特定類型的節點列表。這種情況下,可以調用 Document 對象的 getElementsByTagName() getElementById() 方法來實現。

    document.getElementsByTagName() 返回文檔中具有指定標記名的全部 Element 節點數組(也是 NodeList 類型)。 Element 出現在數組中的順序就是他們在文檔中出現的順序。傳遞給 getElementsByTagName() 的參數忽略大小寫。比如,想定位到第一個 <table> 標記,可以這樣寫: document.getElementsByTagName(“table”)[0] 。例外的,可以使用 document.body 定位到 <body> 標記,因為它是唯一的。

    getElementsByTagName() 返回的數組取決于文檔。一旦文檔改變,返回結果也立即改變。相比, getElementById() 則比較靈活,可以隨時定位到目標,只是要實現給目標元素一個唯一的 id 屬性值。這個我們在《 AJAX 開發簡略》的“級聯菜單”例子中已經使用過了。

    Element 對象也支持 getElementsByTagName() getElementById() 。不同的是,搜索領域只針對調用者的子節點。

    C 、修改文檔內容

    遍歷整棵文檔樹、搜索特定的節點,我們最終目的之一是要修改文檔內容。接下來的三個例子將使用 Node 的幾個常用方法,來演示如何修改文檔內容。

    例子 3 -- sample4_1.htm

    這個例子包含三個文本節點和一個按鈕。點擊按鈕后,三個文本節點和按鈕的順序將被顛倒。程序使用了 Node appendChild() removeChild() 方法。

    <html>

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">

    <title> 無標題文檔 </title>

    <script language="javascript">

    ?????? function reverseNode(node) { // 顛倒節點 node 的順序

    ????????????? var kids = node.childNodes; // 獲取子節點列表

    ????????????? var kidsNum = kids.length; // 統計子節點總數

    ????????????? for(var i=kidsNum-1;i>=0;i--) { // 逆向遍歷子節點列表

    ???????????????????? var c = node.removeChild(kids[i]); // 刪除指定子節點,保存在 c

    ???????????????????? node.appendChild(c); // c 放在新位置上

    ????????????? }

    ?????? }

    </script>

    </head>

    <body>

    <p> 第一行 </p>

    <p> 第二行 </p>

    <p> 第三行 </p>

    <p><input type="button" name="reverseGo" value=" 顛倒 "

    onClick="reverseNode(document.body)"></p>

    </body>

    </html>

    修改文檔_1.jpg 修改文檔_2.jpg?????????????

    例子 4-- sample4_2.htm

    例子 1 通過直接操作 body 的子節點來修改文檔。在 HTML 文檔中,布局和定位常常通過表格 <table> 來實現。因此,例子 4 將演示操作表格內容,將表格的四個單元行順序顛倒。如果沒有使用 <tbody> 標簽,則 <table> 把全部的 <tr> 當做是屬于一個子節點 <tbody> ,所以我們采用數組緩存的方式,把行數據顛倒一下。這個例子同時也演示了如何使用 DOM 創建表格單元行。

    <html>

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">

    <title> 無標題文檔 </title>

    <script language="javascript">

    function reverseTable() {

    ?????? var node = document.getElementsByTagName("table")[0]; // 第一個表格

    ?????? var child = node.getElementsByTagName("tr"); // 取得表格內的所有行

    ?????? var newChild = new Array(); // 定義緩存數組,保存行內容

    ?????? for(var i=0;i<child.length;i++) {

    ????????????? newChild[i] = child[i].firstChild.innerHTML;

    ?????? }

    ?????? node.removeChild(node.childNodes[0]); // 刪除全部單元行

    ?????? var header = node.createTHead(); // 新建表格行頭

    ?????? for(var i=0;i<newChild.length;i++) {

    ????????????? var headerrow = header.insertRow(i); // 插入一個單元行

    ????????????? var cell = headerrow.insertCell(0); // 在單元行中插入一個單元格

    ????????????? // 在單元格中創建 TextNode 節點

    ????????????? cell.appendChild(document.createTextNode(newChild[newChild.length-i-1]));

    ?????? }

    }

    </script>

    </head>

    <body>

    <table width="200" border="1" cellpadding="4" cellspacing="0">

    ??? <tr>

    ??????? <td height="25"> 第一行 </td>

    ??? </tr>

    ??? <tr>

    ??????? <td height="25"> 第二行 </td>

    ??? </tr>

    ??? <tr>

    ??????? <td height="25"> 第三行 </td>

    ??? </tr>

    ??? <tr>

    ??????? <td height="25"> 第四行 </td>

    ??? </tr>

    </table>

    <br>

    <input type="button" name="reverse" value=" 開始顛倒 " onClick="reverseTable()">

    </body>

    </html>

    ???? 修改文檔_3.jpg修改文檔_4.jpg

    例子 5 -- sample4_3.htm

    正如我們在 Node 節點介紹部分所指出的那樣, appendChild() replaceChild() removeChild() insertBefore() 方法會立即改變文檔的結構。下面的例子包含兩個表格,我們試著把表格二的內容替換表格一的內容。

    <html>

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">

    <title> 無標題文檔 </title>

    <script language="javascript">

    function replaceContent() {

    ?????? var table1 = document.getElementsByTagName("table")[0];

    ?????? var table2 = document.getElementsByTagName("table")[1];

    ?????? var kid1 = table1.firstChild.firstChild.firstChild; // 定位到 <td> 節點

    ?????? var kid2 = table2.firstChild.firstChild.firstChild; // 定位到 <td> 節點

    ?????? var repKid = kid2.firstChild; // 定位到表格二 <td> 內含的 TextNode 節點

    ?????? try {

    ????????????? // 用表格二的單元格內容替換表格一的單元格內容,表格二變成沒有單元格內容

    ????????????? kid1.replaceChild(repKid,kid1.firstChild);

    ????????????? // 下面注釋如果開放,將出現 object error ,因為表格二已經被改變

    ????????????? //kid2.replaceChild(kid1.firstChild,kid2.firstChild);

    ?????? }catch(e){

    ????????????? alert(e);

    ?????? }

    }

    </script>

    </head>

    <body>

    <table width="200" border="1" cellspacing="0" cellpadding="0">

    <tbody>

    ??? <tr>

    ??????? <td> 表格一 </td>

    ??? </tr>

    </tbody>

    </table>

    <br>

    <table width="200" border="1" cellspacing="0" cellpadding="0">

    <tbody>

    ??? <tr>

    ??????? <td> 表格二 </td>

    ??? </tr>

    </tbody>

    </table>

    <br>

    <input type="button" name="replaceNode" value=" 替換 " onClick="replaceContent()">

    </body>

    </html>

    ???? 修改文檔_5.jpg修改文檔_6.jpg

    注意,當執行 kid1.replaceChild(repKid,kid1.firstChild); 的時候, table2 的子節點已經被轉移到 table1 了, table2 已經沒有子節點,不能再調用 table2 的子節點。看看代碼的注釋,試著運行一下,應該就知道文檔是怎么改變的了。

    D 、往文檔添加新內容

    在學會遍歷、搜索、修改文檔之后,我們現在試著網文檔添加新的內容。其實沒有什么新意,只是利用我們上述提到的 Node 的屬性和方法而已,還是操作 <table> 標記的內容。有新意的是,我們要實現一個留言簿。是的,留言簿,你可以往里面留言,只是不能刷新噢。

    例子 6 – sample5_1.htm

    <html>

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">

    <title> 無標題文檔 </title>

    <script language="javascript">

    function insertStr() {

    ?????? var f = document.form1;

    ?????? var value = f.str.value;

    ?????? if(value!="") {

    ????????????? // 從最終的 TextNode 節點開始,慢慢形成 <tbody> 結構

    ????????????? var text = document.createTextNode(value); // 新建一個 TextNode 節點

    ????????????? var td = document.createElement("td"); // 新建一個 td 類型的 Element 節點

    ????????????? var tr = document.createElement("tr"); // 新建一個 tr 類型的 Element 節點

    ????????????? var tbody = document.createElement("tbody"); // 新建一個 tbody 類型的 Element 節點

    ????????????? td.appendChild(text); // 將節點 text 加入 td

    ????????????? tr.appendChild(td); // 將節點 td 加入 tr

    ????????????? tbody.appendChild(tr); // 將節點 tr 加入 tbody

    ????????????? var parNode = document.getElementById("table1"); // 定位到 table

    ????????????? parNode.insertBefore(tbody,parNode.firstChild); // 將節點 tbody 插入到節點頂部

    ????????????? //parNode.appendChild(tbody); // 將節點 tbody 加入節點尾部

    ?????? }

    }

    </script>

    </head>

    <body>

    <form name="form1" method="post" action="">

    ??? <input name="str" type="text" id="str" value="">

    ??? <input name="insert" type="button" id="insert" value=" 留言 " onClick="insertStr()">

    </form>

    <table width="400" border="1" cellspacing="0" cellpadding="0" id="table1">

    <tbody>

    ??? <tr>

    ??????? <td height="25"> 網友留言列表: </td>

    ??? </tr>

    </tbody>

    </table>

    </body>

    </html>

    我們之前說過, <table> 的子節點是 <tbody> <tbody> 的子節點才是 <tr> <tr> <td> 的父節點,最后 <td> 內部的 TextNode 節點。所以,往 <table> 增加單元格行要逐級形成,就像往樹里面添加一個枝椏一樣,要有葉子有徑。看看,這個留言簿是不是很簡單啊。這個例子同時也演示了往 <table> 表格標記里面增加內容的另一種方法。

    添加文檔內容_1.jpg 添加文檔內容_2.jpg
    E
    使用 DOM 操作 XML 文檔

    在數據表示方面, XML 文檔更加結構化。 DOM 在支持 HTML 的基礎上提供了一系列的 API ,支持針對 XML 的訪問和操作。利用這些 API ,我們可以從 XML 中提取信息,動態的創建這些信息的 HTML 呈現文檔。處理 XML 文檔,通常遵循“加載 XML 文檔 à 提取信息 à 加工信息 à 創建 HTML 文檔”的過程。下面的例子演示了如何加載并處理 XML 文檔。

    這個例子包含兩個 JS 函數。 loadXML() 負責加載 XML 文檔,其中既包含加載 XML 文檔的 2 DOM 代碼,又有實現同樣操作的 Microsoft 專有 API 代碼。需要提醒注意的是,文檔加載過程不是瞬間完成的,所以對 loadXML() 的調用將在加載文檔完成之前返回。因此,需要傳遞給 loadXML() 一個引用,以便文檔加載完成后調用。

    例子中的另外一個函數 makeTable() ,則在 XML 文檔加載完畢之后,使用最后前介紹過的 DOM 應用編程接口讀取 XML 文檔信息,并利用這些信息形成一個新的 table 表格。

    例子 7 -- sample6_1.htm

    <html>

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">

    <title> 無標題文檔 </title>

    <script language="javascript">

    function loadXML(handler) {

    ?????? var url = "employees.xml";

    ?????? if(document.implementation&&document.implementation.createDocument) {

    ????????????? var xmldoc = document.implementation.createDocument("", "", null);

    ????????????? xmldoc.onload =? handler(xmldoc, url);

    ????????????? xmldoc.load(url);

    ?????? }

    ?????? else if(window.ActiveXObject) {

    ????????????? var xmldoc = new ActiveXObject("Microsoft.XMLDOM");

    ????????????? xmldoc.onreadystatechange = function() {

    ???????????????????? if(xmldoc.readyState == 4) handler(xmldoc, url);

    ????????????? }

    ????????????? xmldoc.load(url);

    ?????? }

    }

    function makeTable(xmldoc, url) {

    ?????? var table = document.createElement("table");

    ?????? table.setAttribute("border","1");

    ?????? table.setAttribute("width","600");

    ?????? table.setAttribute("class","tab-content");

    ?????? document.body.appendChild(table);

    ?????? var caption = "Employee Data from " + url;

    ?????? table.createCaption().appendChild(document.createTextNode(caption));

    ?????? var header = table.createTHead();

    ?????? var headerrow = header.insertRow(0);

    ?????? headerrow.insertCell(0).appendChild(document.createTextNode(" 姓名 "));

    ?????? headerrow.insertCell(1).appendChild(document.createTextNode(" 職業 "));

    ?????? headerrow.insertCell(2).appendChild(document.createTextNode(" 工資 "));

    ?????? var employees = xmldoc.getElementsByTagName("employee");

    ?????? for(var i=0;i<employees.length;i++) {

    ????????????? var e = employees[i];

    ????????????? var name = e.getAttribute("name");

    ????????????? var job = e.getElementsByTagName("job")[0].firstChild.data;

    ????????????? var salary = e.getElementsByTagName("salary")[0].firstChild.data;

    ????????????? var row = table.insertRow(i+1);

    ????????????? row.insertCell(0).appendChild(document.createTextNode(name));

    ????????????? row.insertCell(1).appendChild(document.createTextNode(job));

    ????????????? row.insertCell(2).appendChild(document.createTextNode(salary));

    ?????? }

    }

    </script>

    <link href="css/style.css" rel="stylesheet" type="text/css">

    </head>

    ?

    <body onLoad="loadXML(makeTable)">

    </body>

    </html>

    供讀取調用的 XML 文檔 – employees.xml

    <?xml version="1.0" encoding="gb2312"?>

    <employees>

    ?????? <employee name="J.Doe">

    ????????????? <job>Programmer</job>

    ????????????? <salary>32768</salary>

    ?????? </employee>

    ?????? <employee name="A.Baker">

    ????????????? <job>Sales</job>

    ????????????? <salary>70000</salary>

    ?????? </employee>

    ?????? <employee name="Big Cheese">

    ????????????? <job>CEO</job>

    ????????????? <salary>100000</salary>

    ?????? </employee>

    </employees>

    操作XML文檔.jpg

    處理
    XML 文檔

    脫離 XML 文檔的 AJAX 是不完整的。在本部分未完成之前,有讀者說 AJAX 改名叫 AJAH H 應該代表 HTML 吧)比較合適。應該承認, XML 文檔在數據的結構化表示以及接口對接上有先天的優勢,但也不是所有的數據都應該用 XML 表示。有些時候單純的文本表示可能會更合適。下面先舉個 AJAX 處理返回 XML 文檔的例子再討論什么時候使用 XML

    7.5.1 、處理返回的 XML

    例子 8 -- sample7_1.htm

    在這個例子中,我們采用之前確定的 AJAX 開發框架,稍微修改一下 body 內容和 processRequest 的相應方式,將先前的 employees.xml 的內容讀取出來并顯示。

    body 的內容如下:

    <input type="button" name="read"

    ?value=" 讀取 XML" onClick="send_request('employees.xml')">

    processRequest() 方法修改如下:

    ?????? // 處理返回信息的函數

    ??? function processRequest() {

    ??????? if (http_request.readyState == 4) { // 判斷對象狀態

    ????????? ??if (http_request.status == 200) { // 信息已經成功返回,開始處理信息

    ??????????????????????????? var returnObj = http_request.responseXML;

    ??????????????????????????? var xmlobj = http_request.responseXML;

    ??????????????????????????? var employees = xmlobj.getElementsByTagName("employee");

    ??????????????????????????? var feedbackStr = "";

    ??????????????????????????? for(var i=0;i<employees.length;i++) { // 循環讀取 employees.xml 的內容

    ?????????????????????????????????? var employee = employees[i];

    ?????????????????????????????????? feedbackStr += " 員工: " + employee.getAttribute("name");

    ?????????????????????????????????? feedbackStr +=

    " 職位: " + employee.getElementsByTagName("job")[0].firstChild.data;

    ?????????????????????????????????? feedbackStr +=

    ?" 工資: " + employee.getElementsByTagName("salary")[0].firstChild.data;

    ?????????????????????????????????? feedbackStr +=? "\r\n";

    ??????????????????????????? }

    ??????????????????????????? alert(feedbackStr);

    ??????????? } else { // 頁面不正常

    ??????????????? alert(" 您所請求的頁面有異常。 ");

    ??????????? }

    ??????? }

    }

    運行一下,看來效果還不錯:
    處理返回的xml.jpg

    7.5.2 、選擇合適的 XML 生成方式

    現在的 web 應用程序往往采用了 MVC 三層剝離的設計方式。 XML 作為一種數據保存、呈現、交互的文檔,其數據往往是動態生成的,通常由 JavaBean 轉換過來。由 JavaBean 轉換成 XML 文檔的方式有好幾種,選擇合適的轉換方式往往能達到事半功倍的效果。下面介紹兩種常用的方式,以便需要的時候根據情況取舍。

    A 、類自行序列化成 XML

    類自行序列化成 XML 即每個類都實現自己的 toXML() 方法,選擇合適的 API 、適當的 XML 結構、盡量便捷的生成邏輯快速生成相應的 XML 文檔。顯然,這種方式必須要求每個類編寫專門的 XML 生成代碼,每個類只能調用自己的 toXML() 方法。應用諸如 JDOM 等一些現成的 API ,可以減少不少開發投入。例子 9 是一個利用 JDOM API 形成的 toXML() 方法。

    例子 9 -- toXml() JDOM 實現 -- Employ 類的 toXml() 方法:

    public Element toXml() {?

    ?????? Element employee = new Element(“employee”);

    ?????? Employee.setAttribute(“name”,name);

    ?????? Element jobE = new Element(“job”).addContent(job);

    ?????? employee.setContent(jobE);

    ?????? Element salaryE = new Element(“salary”).addContent(salary);

    ?????? employee.setContent(salaryE);

    ?????? return employee;

    }

    JDOM 提供了現成的 API ,使得序列化成 XML 的工作更加簡單,我們只需要把 toXML() 外面包裝一個 Document ,然后使用 XMLOutputter 把文檔寫入 servlet 就可以了。 toXml() 允許遞歸調用其子類的 toXML() 方法,以便生成包含子圖的 XML 文檔。

    ?????? 使用類自行序列化成 XML 的方式,要每個類都實現自己的 toXML() 方法,而且存在數據模型與視圖耦合的問題,即要么為每個可能的視圖編寫獨立的 toXML() 方法,要么心甘情愿接收冗余的數據,一旦數據結構或者文檔發生改變, toXML() 就要做必要的修改。

    B 、頁面模板生成 XML 方式

    一般的,可以采用通用的頁面模板技術來生成 XML 文檔,這個 XML 文檔可以符合任何需要的數據模型,供 AJAX 靈活的調用。另外,模板可以采用任何標記語言編寫,提高工作效率。下面是一個采用 Struts 標簽庫編寫的 XML 文檔,輸出之前提到的 employees.xml

    Sample8_2.jsp

    <%@ page contentType="application/xml; charset=gb2312" import="Employee"%>

    <%@ page import="java.util.Collection,java.util.ArrayList"%>

    <?xml version="1.0"?>

    <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>

    <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>

    <%

    Employee em1 = new Employee();

    em1.setName("J.Doe");

    em1.setJob("Programmer");

    em1.setSalary("32768");

    Employee em2 = new Employee();

    em2.setName("A.Baker");

    em2.setJob("Sales");

    em2.setSalary("70000");

    Employee em3 = new Employee();

    em3.setName("Big Cheese");

    em3.setJob("CEO");

    em3.setSalary("100000");

    Collection employees = new ArrayList();

    employees.add(em1);

    employees.add(em2);

    employees.add(em3);

    pageContext.setAttribute("employees",employees);

    %>

    <employees>

    <logic:iterate name="employees" id="employee">

    ?????? <employee name="<bean:write name='employee' property='name'/>">

    ????????????? <job><bean:write name="employee" property="job"/></job>

    ????????????? <salary><bean:write name="employee" property="salary"/></salary>

    ?????? </employee>

    </logic:iterate>

    </employees>

    頁面模板生成XML.jpg
    采用頁面模板生成
    XML 方式,需要為每個需要的的數據模型建立一個對立的 JSP 文件,用來生成符合規范的 XML 文檔,而不能僅僅在類的 toXML() 方法中組織對象圖來實現。不過,倒是可以更加方便的確保標記匹配、元素和屬性的順序正確以及 XML 實體正確轉義。

    參考資料中 Philip McCarthy 的文章還描述了一種 Javascript 對象標注的生成方式,本文在此不贅述。有興趣的讀者可以自行查看了解。

    7.5.3 、如何在使用 XML 還是普通文本間權衡

    使用 XML 文檔確實有其方便之處。不過 XML 文檔的某些問題倒是要考慮一下,比如說延遲,即服務器不能立即解析 XML 文檔成為 DOM 模型。這個問題在一定程度上會影響 AJAX 要求的快速反應能力。另外,某些情況下我們并不需要使用 XML 來表示數據,比如說數據足夠簡單成只有一個字符串而已。就好像我們之前提到的數據校驗和級聯菜單的例子一樣。所以,個人認為在下面這些情況下可以考慮使用 XML 來作為數據表示的介質:

    l???????? 數據比較復雜,需要用 XML 的結構化方式來表示

    l???????? 不用考慮帶寬和處理效率支出

    l???????? 與系統其他 API 或者其他系統交互,作為一種數據中轉中介

    l???????? 需要特定各式的輸出視圖而文本無法表示的

    總之,要認真評估兩種表示方式的表示成本和效率,選擇合適的合理的表示方式。

    在關于 AJAX 的系列文章的下一篇,我們將綜合使用 DOM XML ,來實現一個可以持久化的簡單留言簿。另外,還將試著模擬 MSN Space 的部分功能,來體會 AJAX 的魅力

    posted on 2006-09-20 17:28 保爾任 閱讀(164) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     

    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(4)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲精品一品区二品区三品区| 无码人妻精品一二三区免费| 免费永久国产在线视频| 亚洲日本天堂在线| 免费av欧美国产在钱| 亚洲国产精品精华液| 免费a级毛片视频| 成年网在线观看免费观看网址| 高清在线亚洲精品国产二区| 黄页网站在线免费观看| 亚洲精品tv久久久久久久久久| caoporn成人免费公开| 亚洲精品国偷自产在线| a毛片全部播放免费视频完整18| 国产精品亚洲一区二区三区在线| 中文字幕无码毛片免费看| 久久精品国产亚洲夜色AV网站| 久久久久国产精品免费免费不卡 | 免费成人黄色大片| 有码人妻在线免费看片| 亚洲日韩v无码中文字幕 | 天堂亚洲免费视频| 国产亚洲美女精品久久久| 久久精品免费视频观看| 亚洲国产日韩在线人成下载| 四虎成人免费网址在线| 人成午夜免费大片在线观看 | 亚洲欧洲日本国产| 精品久久洲久久久久护士免费 | 国产妇乱子伦视频免费| 亚洲欧美成人一区二区三区| 亚洲国产精品自在拍在线播放 | 亚洲人成网亚洲欧洲无码久久| 拍拍拍无挡视频免费观看1000| 亚洲成a人片在线观看中文!!!| 精品免费国产一区二区三区| 永久免费A∨片在线观看| 亚洲最大成人网色香蕉| 亚洲精品成人在线| 18禁美女黄网站色大片免费观看| 亚洲国产精品18久久久久久|