posts - 297,  comments - 1618,  trackbacks - 0
          說明:參見《JavaScript高級程序設計》第15章"JavaScript中的XML "。
          一.             瀏覽器中的XML DOM支持

           目前只有兩種瀏覽器支持客戶端的XML處理,分別是IEMozilla

          1. IE中的XML DOM支持

          在為IE添加XML支持時,微軟在JavaScript之外另尋了個方案:基于ActiveXMSXML庫。

          1) DOM創建

          對每個新版本的MSXML,都會創建出不同的XML DOM對象,而它們各自的名稱也不相同,MSXML最新的版本是5.0。它存在如下幾種XML DOM實現:

           i)Microsoft XmlDom(最原始的);

          ii)MSXML2.DOMDocument

          iii)MSXML2.DOMDocument3.0

          iv)MSXML2.DOMDocument4.0

          v)MSXML2.DOMDocument5.0

          為確保使用了正確的XML DOM版本,也為避免任何其他錯誤,我們可以創建一個函數來測試每個XML DOM對象字符串,出現錯誤即捕獲:

          function createXMLDOM() {
              var arrSignatures = {"MSXML2.DOMDocument5.0", "MSXML2.DOMDocument4.0", "MSXML2.DOMDocument3.0", "MSXML2.DOMDocument", "Microsoft XmlDom"};
          for (var i= 0; i 
          < arrSignatures.length; i++) {
                 try {
                        var oXmlDom 
          = new ActiveXObject(arrSignatures[i]);
                        return oXmlDom;
          } catch(oError) {
                 //ignore
          }

          throw new Error("SXML is not installed on your system.";
          }

           

          注意:這段在IE中創建XML DOM的代碼在其他瀏覽器會出現錯誤。因此,必須在其之前先進行瀏覽器檢測。

          2) 載入XML

          有了可用的XML DOM對象后,就可以載入XML了,微軟的XML DOM提供兩種方法,.即:loadXML()load()

          loadXML()方法可直接向XML DOM輸入XML字符串,eg.

          var oXmlDom = createXMLDOM();

          oXmlDom.loadXML(“<root><child/></root>”);

          load()方法用于從服務器上載入XML文件,不過load()方法只可以載入與包含JavaScript的頁面存儲于同一個服務器上的文件,即:不可以通過其他人的服務器載入XML文件。

          還有兩種載入文件的模式:同步與異步。以同步模式載入時,JavaScript代碼會等待文件完全載入后才繼續執行代碼;而以一步模式載入時,不會等待,可以使用事件處理函數來判斷文件是否完全載入了。默認情況下,為異步載入。要進行同步載入,需設置async特性為false,如下:

          oXmlDom. async = false;

          然后使用load()方法,并給出要載入的文件名:

          oXmlDom.load(“test.xml”);

          異步載入文件時,要使用readyState特性和onreadystatechange事件處理函數:

          readyState特性有五種可能的值:

               0——DOM尚未初始化任何信息;

               1——DOM尚未載入數據;

               2——DOM完成了數據載入;

               3——DOM已經可用,不過某些部分可能還不能用;

               4——DOM已經完全被載入,可以使用了。

          一旦readyState的值發生變化,就會觸發onreadystatechange事件。使用該函數,就可以在DOM完全載入時,發出通知:

          oXmlDom.onreadystatechange = function() {

              if (oXmlDom.readyState == 4) {

                 alert(“已完全載入!”);

          }

          }

          必須在調用load()方法前分配好onreadystatechange事件處理函數,如下所示:

          oXmlDom.onreadystatechange = function() {

              if (oXmlDom.readyState == 4) {

                 alert(“已完全載入!”);

          }

          }

          oXmlDom.load(“test.xml”);

          注意:事件處理函數代碼使用oXmlDom而不是this關鍵字,這是JavaScriptActiveX對象的特殊之處。

          load()方法可以接受部分的、相對的或者完整的XML文件路徑。eg.

          oXmlDom.load(“test.xml”);

          oXmlDom.load(“../test.xml”);

          oXmlDom.load(“http://www.amigo.com/test.xml”)

          3) 獲取XML

          XML載入到DOM中后,還需將XML取出來,微軟為每個節點(包括文檔節點)都添加了一個xml特性,使得這個操作十分方便,它會將XML表現形式作為字符串返回。所以獲取載入后的XML十分簡單:

          oXmlDom.load(“test.xml”);

          alert(oXmlDom.xml);

          也可以獲取某個特定節點的XML:

          var oNode = oXmlDom.documentElements.childNodes[1];

          alert(oNode.xml);

          xml特性是只讀的,如果嘗試直接對其進行賦值會產生錯誤。

          4) 解釋錯誤

          微軟的XML DOMparseError的特性包含了關于解析XML代碼時所遇到的問題的所有信息。

          parseError特性實際上是包含以下特性的對象:

               errorCode——表示所發生的錯誤類型的數字代號(沒有錯誤時為0);

               filePos——錯誤發生在文件中的位置;

               line——遇到錯誤的行號;

               linepos——在遇到錯誤的那一行上的字符的位置;

               reason——對錯誤的一個解釋;

               srcText——造成錯誤的代碼;

                url——造成錯誤的文件的URL(如果可用)。

          可直接對parseError自身取值,它會返回errorCode的值。Eg.

          if (oXmlDom. parseError != 0) {

              //…

          }

          可以使用parseError對象來創建自己的錯誤對話框:

          if (oXmlDom. parseError != 0) {

              var oError = oXmlDom. parseError;

              alert(“錯誤發生!\nerrorCode: ” + oError. errorCode

          + “\nLine:” + oError.line + “\nLine Pos: ” + oError. linepos

          + “\nReason: ” + oError. reason);

          }

           

          2. Mozilla中的XML DOM支持

           略。

           

          3. 通用接口

             有了跨瀏覽器的解決方案時,使用XML DOM進行開發才真正有用。IEMozilla的實現之間有著很明顯的區別,開發時會造成很嚴重的問題。需要找出一套能在兩種瀏覽器中都可以使用XML DOM的通用方法。

          1) 修改DOM創建

          最簡單方法是創建偽類,使其通過var oXmlDom = new XmlDom ();來創建XML DOM。在其構造函數中進行瀏覽器檢測,eg.

          function XmlDom() {

                 if (window.ActiveObject) {

                 //IE-specific code

          } else if (document.implementation && document.implementation.createDocument) {

                 //DOM-specific code

          } else {

                 throw new Error(“你的瀏覽器不支持XML DOM對象”);

          }

          }

          2) IE分支

          將上節的IE中創建DOM的代碼轉貼到上述代碼中。

          3) Mozilla分支

          略。

          4) 完整代碼

          完整代碼如下所示:

           

          function XmlDom() {
          if (window.ActiveXObjext) {
          var arrSignatures = {"MSXML2.DOMDocument5.0", "MSXML2.DOMDocument4.0", "MSXML2.DOMDocument3.0", "MSXML2.DOMDocument", "Microsoft XmlDom"};
          for (var i= 0; i 
          < arrSignatures.length; i++) {
                               try {
                                      var oXmlDom 
          = new ActiveXObject(arrSignatures[i]);
                                      return oXmlDom;
          } catch(oError) {
                               //ignore
          }
          }
          throw new Error("MSXML is not installed on your system.");
          } else if (document.implementation && document.implementation.createDocument) {
                 var oXmlDom 
          = document.implementation.createDocument("", "", null);
                 oXmlDom.parseError 
          = {
                        
          valueOf: function() {return this.errorCode;},
                  toString: function() {return this.errorCode.toString()};
          }
          oXmlDom.addEventListener("load", function()) {
                 this.__checkForErrors__();
                 this.__changeReadyState__(4);
          }, false);
          return oXmlDom;
          } else {
                 throw new Error("你的瀏覽器不支持XML DOM對象");
          }
          }

          if (isMoz) {
          Document.prototype.readyState 
          = 0;
           
          Document.prototype.onreadystatechange = null;
           
          Document. prototype.__changeReadyState__ = function(iReadyState) {
               this.readyState 
          = iReadyState;
               
          if (typeof this.onreadystatechange == “function”) {
                 this.onreadystatechange();
          }
          };

          Document.prototype.__initError__ 
          = function() {
               this.parseError.errorCode 
          = 0;
               
          this.parseError..filepos = -1;
               
          this.parseError..line = -1;
               
          this.parseError..lineppos = -1;
               
          this.parseError..reason = null;
               
          this.parseError.srcText = null;
               
          this.parseError..url = null;
          };

          Document.prototype.__checkForErrors__ 
          = function() {
               if (this.documentElement.tagName 
          == “parseError”) {
                 var reError 
          />([\s\S]*?)Location:([\s\S]*?)Line Number (\d+), Column (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/;
                 reError.text(this.xml);
                 this.parseError..errorCode = -999999;
                 this.parseError..reason = RegExp.$1p;
                 this.parseError..url = this.parseError..$2;
                 this.parseError..line = pauseInt(RegExp.$3);
                 this.parseError..linepos = parseInt(RegExp.$4);
                 this.parseError..srcText = RegExp.$5;
          }
          };

          Document.prototype.loadXML = function(sXml) {
               this.__initError__();
               this.__changeReadyState__(1);
               var oParser = new DomParser();
               var oXmlDom = oParser.parseFromString(sXml, "text/xml");
               while (this.firstChild) {
                 this.removeChild(this.firstChild);
          }

          for (var = 0; I 
          < oXmlDom.childNodes.length; i++) {
                 var oNewNode 
          = this.importNode(oXmlDom.childNodes[i], true);
                 this.appendChild(oNewNode);
          }

          this.__checkForErrors__();
          this.__changeReadyState__(4);
          };

          Document.prototype.__load__ 
          = Document.prototype.load;
          Document.prototype.load = function(sURL) {
               this.__initError__();
               this.__changeReadyState__(1);
               this.__load__(sURL)L
          };

          Node.prototype.__defineGetter__("xml", function()) {
               var oSerializer 
          = new XMLSerializer();
               return oSerializer.serializeToString(this. "text/xml");
          });
          }

           

          二.             瀏覽器對XPath的支持

           XPath是一種可以在XML代碼中定位數據的方式。

          1.       簡介

          每個XPath表達式有兩部分:一個上下文節點和一個節點模式。前者提供了節點模式起始的位置。節點模式是由一個或多個節點選擇器組成的字符串。

          Eg.

          <?xml version=”1.0”?>
              
          <employees>
                     
          <employee title=”軟件工程師”>
                            
          <name>阿蜜果</name>
                     
          </employee>
                     
          <employee title=”測試工程師”>
                            
          <name>amigo</name>
                     
          </employee>
                 
          </employees>

          XPath表達式employee/name,匹配的是<name>阿蜜果</name><name>amigo</name>,若要選擇<employee/>元素的第一個<name/>元素,可用employee[position() == 1]/name。在XPath中,方框記號用于為某個節點提供更加確切的信息,position()用于返回元素在父節點下的位置。

           除了未知和名稱外,還可以使用不同的方法來匹配元素,若要選擇所有title特性為“軟件工程師”的<employee/>元素,對應的表達式為:

           employee[@title = “軟件工程師”]

           其中@attribute的縮寫。

          2. IEXPath的支持

          每個節點的都有兩個可用于獲取匹配XPath模式的節點的方法:

          selectNodes():用于匹配某個模式的節點的集合;

          selectSingleNode():用于返回匹配給定模式的第一個節點。

           eg. varlstNodes = oXmlDom.documentElement.selectNodes(“employee/name”);

           返回包含所有匹配給定模式的節點的NodeList,可以通過如下方式迭代所有的元素:

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

              alert(varlstNodes[i]);

          }

          如果沒有匹配的節點,返回的NodeListlength0

          3. MozillaXPath的支持

          略。

          三.             瀏覽器的XSLT支持

           XSLT:可擴展樣式表語言轉換,可由一些模板組成。模板屬于XML的某個特性的一部分(使用XPath指定),它可以決定為這一部分輸出什么文本。通過為不同的元素和條件定義模板,XSLT樣式表變成了一種XML的解析器。

          1. IEXSLT的支持

          MSXML3.0開始,IE就完全支持XSLT1.0了。對于在IE6.0以前的版本,還需要安裝新版的MSXML

          最簡單的XSLT轉換的方法是:分別將XML源代碼和XSLT文件載入各自的DOM,并使用特有的transformNode方法:

           oXmlDom.load(“employees.xml”);

           oXslDom.load(“employees.xslt”);

           var sResult = oXmlDom. transformNode(oXslDom);

           其實,也可以不從文檔層次轉換,而從節點層次轉換,如果從某個節點調用transformNode(),則從這個點開始轉換,但是XSLT能訪問包含這個節點的整個XML文檔。

           IE中使用XSLT的另外一個比較復雜的方法是,使用XSL模板和處理器。這種方法必須使用MSXML的其他幾個ActiveX控件。首先XSLT文件必須載入到一個自由線程DOM文檔中,代碼如下:

           var oXslDom = new ActiveXObject(“MSXML2.FreeThreadedDOMDocumnet”);

           oXslDom.asyn = false;

           oXslDom.load(“employees.xml”);

           自由線程DOM文檔建立并加載好后,必須將其分配到XSL模板中,這是另一個ActiveX對象:

           var oTemplate = new ActiveXObject(“:MSXML2.XSLTemplate”);

           oTemplate.stylesheet = oXslDom;

           然后,可以用XSL模板來創建一個XSL處理器:

           var oProcessor = oTemplate.createProcessor();

           創建處理器后,將input特性設置為要進行轉換的XML DOM節點,然后調用transform()方法:

           oProcessor.input = oXmlDom;

           oProcessor.transform();

           然后將從output特性中訪問結果字符串:

           var sResult = oProcessor.output;

           這個復雜的方法模仿了transformNode()的功能,但該方法允許更多地控制XSLT

           注意:MSXML只支持XSLT1.0MSXML的開發自從轉到.NET Framework后就停止了。可能在未來的某天,JavaScript會允許訪問XMLXSL.NET對象。

          2. MozillaXSLT的支持

          略。

          posted on 2007-08-13 13:19 阿蜜果 閱讀(2827) 評論(6)  編輯  收藏 所屬分類: Javascript


          FeedBack:
          # re: JavaScript學習筆記——JavaScript中的XML
          2007-08-13 15:08 | 楊愛友
          搶到了。
          好快的速度,上午還問了下‘其他章節呢’,中午就下好了,而且寫這么多。仔細研讀...  回復  更多評論
            
          # re: JavaScript學習筆記——JavaScript中的XML[未登錄]
          2007-08-13 15:12 | 阿蜜果
          @ 楊愛友
          嘻嘻,是昨晚寫好的
          今天中午上傳了一下
          :)
            回復  更多評論
            
          # re: JavaScript學習筆記——JavaScript中的XML
          2007-08-27 10:43 | Candlelighting
          有沒有兼容fireFox的,對xml的操作的例子
          在下面代碼中第一個if語句中的alert(xmldoc.xml);在用fireFox瀏覽的時候會跳出undefined...試過好幾個例子了,不知道問題出在哪里.
          var url = "employees.xml";
          if(document.implementation&&document.implementation.createDocument) {
          var xmldoc = document.implementation.createDocument("", "", null);
          xmldoc.load(url);
          alert(xmldoc.xml);
          }
          else if(window.ActiveXObject) {
          var xmldoc = new ActiveXObject("Microsoft.XMLDOM");
          xmldoc.onreadystatechange = function() {
          if(xmldoc.readyState == 4) handler(xmldoc, url);
          }
          xmldoc.load(url);
          alert(xmldoc.xml);
            回復  更多評論
            
          # re: JavaScript學習筆記——JavaScript中的XML
          2007-08-27 10:52 | Candlelighting
          JavaScript高級程序設計
          這本書很好,可惜我才剛剛開始看。  回復  更多評論
            
          # re: JavaScript學習筆記——JavaScript中的XML
          2007-08-28 08:53 | Candlelighting
          就應該是Undefined,因為firefox里的xmldom就沒有xml的屬性...  回復  更多評論
            
          # re: JavaScript學習筆記——JavaScript中的XML
          2007-09-06 13:48 | 喝小酒泡尼姑
          FireFox對XPath的支持要難于使用得多,你需要使用到XPathEvaluator和XPathResult對象,并使用 XPathEvaluator的evaluate()方法計算XPath表達式,evaluate()接收五個參數:XPath表達式,上下文節點,命名空間解釋程序
          參見:
          http://www.cnblogs.com/thinhunan/archive/2006/12/19/596985.html  回復  更多評論
            
          <2007年8月>
          2930311234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

                生活將我們磨圓,是為了讓我們滾得更遠——“圓”來如此。
                我的作品:
                玩轉Axure RP  (2015年12月出版)
                

                Power Designer系統分析與建模實戰  (2015年7月出版)
                
               Struts2+Hibernate3+Spring2   (2010年5月出版)
               

          留言簿(263)

          隨筆分類

          隨筆檔案

          文章分類

          相冊

          關注blog

          積分與排名

          • 積分 - 2296322
          • 排名 - 3

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 焉耆| 晋江市| 阿拉善左旗| 贡嘎县| 饶平县| 车险| 和龙市| 聂荣县| 沙湾县| 澳门| 崇明县| 屯留县| 安达市| 黄浦区| 正镶白旗| 安平县| 安新县| 牟定县| 安远县| 高清| 岚皋县| 九寨沟县| 黔江区| 炎陵县| 容城县| 辰溪县| 五原县| 长葛市| 天峻县| 鄱阳县| 河源市| 兴和县| 苏尼特右旗| 瑞丽市| 阿巴嘎旗| 温州市| 呼和浩特市| 平利县| 阿勒泰市| 历史| 安图县|