一日精通Ajax技術(shù)_Xml教程

      編輯Tag賺U幣
      教程Tag:暫無Tag,歡迎添加,賺取U幣!

      推薦:XML卷之實戰(zhàn)錦囊(4):選單連動
      現(xiàn)在我們做個在IE里應(yīng)用XML的一個小例子:解決雙下拉選單的連動問題。大家最常見的可能就是選取省份后改變城市選項的例子了,那我們就來嘗試著用XML來完成吧。 以前介紹的一些功能我是直接用X


        Ajax這個名稱怎么來的,本人也不得而之了,大概是(Active Javascript Action Xml)吧,說白一點就是運用了 javascript、xmlhttp和xmldom技術(shù)及網(wǎng)站后臺來處理用戶的一些操作的方法吧。

        那么本人就分三步來說明如何使用 Ajax 技術(shù)來做開發(fā)。

        一、用 javascript 操作 xmlhttp 對象

        二、服務(wù)器部對xmlhttp請求的響應(yīng)(PHP范例)

        三、xmldom 的使用方法

        先說第一部份:

        一、用 javascript 操作 xmlhttp 對象

        IE7, Mozilla ,Firefox等瀏覽器中,javascript是內(nèi)置有 XMLHttpRequest 這個對象的,但I(xiàn)E5 則沒有,需要用如下方法來啟動:
      //IE 6
      try{ xhttp = new ActiveXObject("Msxml2.XMLHTTP";} catch(e){ ; }
      //IE5
      if(xhttp == null) try { xhttp = new ActiveXObject("Microsoft.XMLHTTP";} catch(e){ ; }

        那考慮不同瀏覽器的兼容,啟動一個xmlhttp一般都要按如下方式:

      CODE:[Copy to clipboard]var xhttp = null;

      if(window.XMLHttpRequest){ //IE7, Mozilla ,Firefox 等瀏覽器內(nèi)置該對象

      xhttp = new XMLHttpRequest();

      }else if(window.ActiveXObject){ //IE6、IE5

      try{ xhttp = new ActiveXObject("Msxml2.XMLHTTP");} catch (e){ ; }

      if( xhttp == null) try { xhttp = new ActiveXObject("Microsoft.XMLHTTP");} catch (e){; }

      }

        對于 xmlhttp 的使用,一般遵守如下的順序:

        1、初始化 xmlhttp 對象(上文);

        2、打開鏈接

        方法

      xhttp.open("GET", purl, true);

        參數(shù)一:用 GET 或 POST 方式發(fā)送數(shù)據(jù)

        參數(shù)二、請求網(wǎng)址(只能請求你服務(wù)器上的資源,一般瀏覽器安全限制不能讀取跨域的數(shù)據(jù))

        參數(shù)三、true 表示異步傳輸(服務(wù)器返回信息完成前,你可以進(jìn)行其它操作),false 表示阻斷方式的傳輸。

        3、設(shè)定要發(fā)送的 http 請求頭

        方法:

      xhttp.setRequestHeader(key,value);

        一般來說,默認(rèn)要發(fā)送的頭是:xhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded";

        這種表示發(fā)送的內(nèi)容類型的請求頭用于發(fā)送文本數(shù)據(jù),而且javascript默認(rèn)是以unicode發(fā)送的,還有另外一種形式是:xhttp.setRequestHeader("Content-Type","multipart/form-data";這表示發(fā)送二制形式的數(shù)據(jù),由于安全性原因,javascript一般不能用這種方式來發(fā)送數(shù)據(jù),所以這個頭一般沒什么用。

        如果你的網(wǎng)站開啟了使用 refer 參數(shù)來防盜鏈,那么你必須用這個方法指定 Refer 參數(shù),或者如果用戶需要登錄才能進(jìn)行某操作,那么要指定 Cookie 的請求頭。

        4、send 數(shù)據(jù)

        方法:xhttp.send(postdata);

        對于用 get攻手請求,不需要指定postdata,直接用 test.php?a=a&b=b 這樣形式的網(wǎng)址來請求即可。

        如果是post方式,需要用 key1=value2&key2=value2 這樣的形式來對數(shù)據(jù)進(jìn)行處理,把它合并在 postdata 字串中,然后發(fā)送。

        注意事項:

        javascript默認(rèn)發(fā)送數(shù)據(jù)的方式是unicode,處理返回的數(shù)據(jù)必須是utf-8格式,因此,在發(fā)送的時候,需要用escape()函數(shù)來處理postdata和網(wǎng)址的value,在服務(wù)器上必須還原這些value,并把unicode轉(zhuǎn)為頁面編碼值,因此如果用 jsp 或 asp.net 都會比較簡單,但如果用php處理起來是什么費勁的,等下會教你如何做。

        5、確認(rèn)服務(wù)器返回資料完成下載

        [1] 如果用阻斷的方式來發(fā)送請求,那么直接用 if(xhttp.readyState == 4)就能判斷是否完成。

      readyState 的具體屬性值為:
      0 沒open
      1 沒send
      2 狀態(tài)未知
      3 正在傳送
      4 傳送完成

        當(dāng)然為了保障起見,還需要加多一重判斷,就是 if(xhttp.status == 200) ,status 就是 http 協(xié)議里的返回頭代碼

      1xx 表示(唉呀,忘記了)
      2xx 表示成功的信息
      3xx 表示頁面轉(zhuǎn)移
      4xx 頁面不存在
      5xx 表示服務(wù)器的各種錯誤

        如果你的頁面沒特殊處理,一般用 if(xhttp.status == 200) 來確信內(nèi)容返回是正確的

        [2] 如果用異步傳輸,需要用 onreadystatechange 的事件來監(jiān)聽

      xhttp.onreadystatechange = function()
      {
      //這里來進(jìn)行上面阻斷方式的判斷
      if(myajax.xhttp.readyState == 4){
      if(myajax.xhttp.status == 200){
      //要進(jìn)行的后續(xù)操作
      }
      }
      }

        6、獲取返回結(jié)果

      屬性:
      [1]xhttp.responseBody;
      [2]xhttp.responseStream;
      [3]xhttp.responseXml;
      [4]xhttp.responseText;

        其中1、2都是二進(jìn)制的方式,一般很少會用到,4不用看都知道了

        如果服務(wù)端無意外的話[3]返回的是一個xmldom的對象

        二、服務(wù)器部對xmlhttp請求的響應(yīng)(PHP范例)

        為了簡化操作,在這里把 xmlhttp的各作操作封裝為一個類

        CODE:[Copy to clipboard]function DedeAjax(WiteOKFunc){ //WiteOKFunc 為異步狀態(tài)事件處理函數(shù)

      //xmlhttp和xmldom對象
      this.xhttp = null;
      this.xdom = null;

      //post或get發(fā)送數(shù)據(jù)的鍵值對
      this.keys = Array();
      this.values = Array();
      this.keyCount = -1;

      //http請求頭
      this.rkeys = Array();
      this.rvalues = Array();
      this.rkeyCount = -1;
      //請求頭類型
      this.rtype = 'text';

      //初始化xmlhttp
      if(window.XMLHttpRequest){//IE7, Mozilla ,Firefox 等瀏覽器內(nèi)置該對象
      this.xhttp = new XMLHttpRequest();
      }else if(window.ActiveXObject){//IE6、IE5
      try { this.xhttp = new ActiveXObject("Msxml2.XMLHTTP");} catch (e) { }
      if (this.xhttp == null) try { this.xhttp = new ActiveXObject("Microsoft.XMLHTTP");} catch (e) { }
      }
      this.xhttp.onreadystatechange = WiteOKFunc;
      //rs: responseBody、responseStream、responseXml、responseText

      //以下為成員函數(shù)
      //--------------------------------

      //初始化xmldom
      this.InitXDom = function(){
      var obj = null;
      if (typeof(DOMParser) != "undefined") { // Gecko、Mozilla、Firefox
      var parser = new DOMParser();
      obj = parser.parseFromString(xmlText, "text/xml");
      } else { // IE
      try { obj = new ActiveXObject("MSXML2.DOMDocument");} catch (e) { }
      if (obj == null) try { obj = new ActiveXObject("Microsoft.XMLDOM"); } catch (e) { }
      }
      this.xdom = obj;
      };

      //增加一個POST或GET鍵值對
      this.AddKey = function(skey,svalue){
      this.keyCount ;
      this.keys[this.keyCount] = skey;
      this.values[this.keyCount] = escape(svalue);
      };

      //增加一個Http請求頭鍵值對
      this.AddHead = function(skey,svalue){
      this.rkeyCount ;
      this.rkeys[this.rkeyCount] = skey;
      this.rvalues[this.rkeyCount] = svalue;
      };

      //清除當(dāng)前對象的哈希表參數(shù)
      this.ClearSet = function(){
      this.keyCount = -1;
      this.keys = Array();
      this.values = Array();
      this.rkeyCount = -1;
      this.rkeys = Array();
      this.rvalues = Array();
      };

      //發(fā)送http請求頭
      this.SendHead = function(){
      if(this.rkeyCount!=-1){ //發(fā)送用戶自行設(shè)定的請求頭
      for(;i<=this.rkeyCount;i ){
      this.xhttp.setRequestHeader(this.rkeys[i],this.rvalues[i]);
      }
      }
       if(this.rtype=='binary'){
      this.xhttp.setRequestHeader("Content-Type","multipart/form-data");
      }else{
      this.xhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
      }
      };

      //用Post方式發(fā)送數(shù)據(jù)
      this.SendPost = function(purl){
      var pdata = "";
      var i=0;
      this.state = 0;
      this.xhttp.open("POST", purl, true);
      this.SendHead();
      if(this.keyCount!=-1){ //post數(shù)據(jù)
      for(;i<=this.keyCount;i ){
      if(pdata=="") pdata = this.keys[i] '=' this.values[i];
      else pdata = "&" this.keys[i] '=' this.values[i];
      }
      }
      this.xhttp.send(pdata);
      };

      //用GET方式發(fā)送數(shù)據(jù)
      this.SendGet = function(purl){
      var gkey = "";
      var i=0;
      this.state = 0;
      if(this.keyCount!=-1){ //get參數(shù)
      for(;i<=this.keyCount;i ){
      if(gkey=="") gkey = this.keys[i] '=' this.values[i];
      else gkey = "&" this.keys[i] '=' this.values[i];
      }
      if(purl.indexOf('?')==-1) purl = purl '?' gkey;
      else purl = purl '&' gkey;
      }
      this.xhttp.open("GET", purl, true);
      this.SendHead();
      this.xhttp.send();
      };

      } // End Class DedeAjax
      上面代碼保存為: dedeajax.js

      ok 那現(xiàn)在做個最簡單的測試吧
      test.htm

      CODE:[Copy to clipboard]<script language='javascript' src='dedeajax.js'></script>
      <script language='javascript'>
      function WiteOK()
      {
      var myinfo = document.getElementById("myinfo");
      if(myajax.xhttp.readyState == 4){
      if(myajax.xhttp.status == 200){
      myinfo.innerHTML = myajax.xhttp.responseText;
      }
      }
      }
      var myajax = new DedeAjax(WiteOK);
      myajax.AddKey("key1","----------------------------");
      myajax.SendPost("test.php");

      </script>

      <div id='myinfo'><div>
      test.php


      CODE:[Copy to clipboard]<?
      header("Content-Type: text/html; charset=gb2312");
      echo $_POST['key1'];
      ?>
      看到了什么了呢?不用激動,真正讓你頭痛的東西還沒有出來。

      把類里面的

      CODE:[Copy to clipboard]this.AddKey = function(skey,svalue){
      this.keyCount ;
      this.keys[this.keyCount] = skey;
      this.values[this.keyCount] = svalue;//escape(svalue);
      };
      escape 屏蔽掉

      發(fā)送
      myajax.AddKey("key1","-----中---國----人-----";

      看到什么了,亂碼是吧?呵呵,這回開始頭大了

      先把 escape放回去
      this.values[this.keyCount] = escape(svalue);

      那么看到的就是
      -----%u4E2D---%u56FD----%u4EBA-----

      如何把 %u4E2D 這些東西弄回來呢?對于php而言這是一個很復(fù)雜的問題,如果用asp就簡單多了

      下面是我寫的一個函數(shù):


      CODE:[Copy to clipboard]//unicode url編碼轉(zhuǎn)gbk編碼函數(shù)
      function Unicode2Gbk($str)
      {
      //載入對照詞典
      if(!isset($GLOBALS['GbkUniDic']))
      {
      $ds = file("./data/gbk_unicode.dic");
      foreach($ds as $l){
      $GLOBALS['GbkUniDic'][hexdec('0x'.substr($l,0,4))] = substr($l,5,4);
      }
      }
      //處理字符串
      $glen = strlen($str);
      $okstr = "";
      for($i=0; $i < $glen; $i )
      {
      if( $glen-$i > 4){
      if($str[$i]=='%' && $str[$i 1]=='u'){
      $uni = hexdec('0x'.substr($str,$i 2,4));
      if(isset($GLOBALS['GbkUniDic'][$uni])){
      $uni = $GLOBALS['GbkUniDic'][$uni];
      $okstr .= chr(hexdec(substr($uni,0,2))).chr(hexdec(substr($uni,2,2)));
      }
      else $okstr .= "&#{".hexdec("0x".$uni).";";
      $i = $i 5;
      }
      else $okstr .= $str[$i];
      }
      else $okstr .= $str[$i];
      }
      return $okstr;
      }
      詞典文件: http://www.ce86.com/myimg/data.rar


      把test.php 輸出改為

      echo Unicode2Gbk($_POST['key1']);

      正常了吧

      以下說下面和xml有關(guān)的東西的了

        三、xmldom 的使用方法
        
        由于本文僅是牽針引線的作用,這一章就簡單些,因為針對的是 php ,如果針對的是 asp.net 或 jsp 寫涉及 web server 類的通信,已經(jīng)不單純是 ajax 的問題了,本章的任務(wù)是把test2.php

      CODE:[Copy to clipboard]<?
      header("Content-Type: text/xml; charset=gb2312");
      echo '<'.'?'."xml version=\"1.0\" encoding=\"gb2312\" ".'?'.">
      <myhome>
      <item sex=\"男\(zhòng)">我是小一</item>
      <item sex=\"女\">我是小二</item>
      </myhome>
      ";
      ?>這個xml文檔在客戶端用自己的方式展現(xiàn)出來。因為xml這種東西比較麻煩,所以語法也必須嚴(yán)格,test2.htm的頁面的源碼為

      CODE:[Copy to clipboard]<html>
      <head>
      <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
      <title>ajax測試</title>
      </head>
      <body onload="WiteLoadDocument()">
      <script language='javascript' src='dedeajax.js'></script>
      <script language='javascript'>
      var myajax = new DedeAjax(WiteOK);
      function WiteOK()
      {
      var myinfo = document.getElementById("myinfo");
      var mydom = null;
      myinfo.innerHTML = "以下是處理結(jié)果:<br/>";
      if(myajax.xhttp.readyState == 4){
      mydom = myajax.xhttp.responseXml;
      alert(mydom);
      }
      }
      function WiteLoadDocument()
      {
      myajax.SendGet("test2.php");
      }
      </script>
      <div id='myinfo'><div>
      </body>
      </html>
      在IE中測試一下,如果彈出的對話框是 [object] 就表示成功獲得返回的xml的xmldoc了。

      那下面是處理:

      CODE:[Copy to clipboard]function WiteOK()
      {
      var myinfo = document.getElementById("myinfo");
      var mydom = null;
      myinfo.innerHTML = "以下是處理結(jié)果:<br/>";
      if(myajax.xhttp.readyState == 4){
      mydom = myajax.xhttp.responseXml;
      var nodeList = mydom.selectNodes("/myhome/item");
      var mynode = null;
      var myatt = null;
      var mysex = "";
      for(i=1;i<=nodeList.length;i )
      {
      mynode = nodeList[i-1];
      for(j=0;j < myinfo.attributes.length;j )
      {
      if(!mynode.attributes[j]) break;
      myatt = mynode.attributes[j];
      if(myatt.name=='sex') mysex = myatt.value;
      }
      myinfo.innerHTML = "我是:" mynode.text ",我的性別是:" mysex "<br/>";
      }
      }
      }

      結(jié)果:

      CODE:[Copy to clipboard]以下是處理結(jié)果:
      我是:我是小一,我的性別是:男
      我是:我是小二,我的性別是:女
      OK,目的已經(jīng)達(dá)到

        關(guān)于dom的部份只在IE6中測試過,可能在firefox中會有問題,大家可能參考與兼容性有關(guān)的文檔。

      分享:XML入門教程:XML CDATA
      所有XML文檔中的文本均會被解析器解析。 只有CDATA區(qū)段(CDATA section)中的文本會被解析器忽略。 Parsed Data XML解析器通常會解析XML文檔中所有的文本。 當(dāng)某個XML元素被解析時,其

      來源:模板無憂//所屬分類:Xml教程/更新時間:2008-08-22
      相關(guān)Xml教程