JavaScript中的XML

浏览器中的XML DOM支持
1、IE中的XML DOM 支持
在为IE添加XML支持时,微软在JavaScript之外另寻了个方案:基于ActiveX的MSXML库。
1)、DOM创建
如果尝创建不存在于客户端机器上的ActiveX对象,IE就会抛出错误并停止所有执行。为确保使用了正确的XML DOM版本,也为避免任何其他错误:
<script type="text/javascript">
        function createXMLDOM() {
            var arrSignatures = ["MSXML2.DOMDocument.5.0", "MSXML2.DOMDocument.4.0", "MSXML2.DOMDocument.3.0", "MSXML2.DOMDocument", "Microsoft.XmlDom"];
            for (var i = 0; i < arrSignatures.length; i++) {
                try {
                    var oXmlDom = new ActiveXObject(arrSignatures[i]);
                    return oXmlDom;
                }
                catch (oError) {
               
                }
            }
            throw new Error("MSXML is not installed on your system.");
        }
    </script>
arrSingatures数组,包含了所有可能的XML DOM字符串,且按照最新到最旧降序排列。
2)、载入XML
微软的XML DOM有两种载入XML的方法:loadXML()和load().
loadXML()方法可直接向XML DOM输入XML字符串:
oXmlDom.loadXML("<root><child/></root>");
load()方法用于从服务器上载入XML文件。
还有两种载入文件的模式:同步和异步。以同步模式载入文件时,JavaScript代码会等待文件完全载入后才继续执行代码;而以异步模式载入时,不会等待,可以使用事件处理函数来判断文件是否完全载入了。默认情况下,文件按照异步模式载入。要进行同步载入,只需设置async特性为false:
oXmlDom.async = false;
然后使用load()方法,并给出要载入的文件名:
oXmlDom.load("test.xml");
执行这一行代码后,oXmlDom会包含能表示XML文件结构的一个DOM文档,这样就可以使用DOM所有的特性和方法了:
alert("Tag name of the root emement is " + oXmlDom.documentElement.tagName);
alert("The root emement has this many children: " + oXmlDOm.documentElement.childNodes.length);
异步载入文件时,要使用readyState特性和onreadystatechange事件处理函数:
readyState特性有五种可能的值:
0:DOM尚未初始化任何信息;
1:DOM正在载入数据;
2:DOM完成了数据载入;
3:DOM已经可用,不过某些部分可能还不能用;
4:DOM已经完全被载入,可以使用了。
必须在调用load()方法前分配好onreadystatechange事件处理函数,就像下面代码中那样:
oXmlDom.onreadystatechange = function()
{
 if(oXmlDom.readyState == 4)
 {
  alert("Done");
 }
};
oXmlDom.load("test.xml");
3、获取XML
获取载入后的XML:
oXmlDom.load("test.xml");
alert(oXmlDom.xml);
也可以仅获取某个特定节点的XML:
var oNode = oXmlDom.documentElements.childNodes[1];
alert(oNode.xml);
xml特性是只读的,如果尝试直接对其赋值会产生错误。
4、解释错误
parseError特性实际上是包含以下特性的对象:
errorCode:表示所发生的错误类型的数字代号(当没有错误时为0);
filePos:错误发生有文件中的位置;
line:遇到错误的行号;
linepos:在遇到错误的那一行上的字符的位置;
reason:对错误的一个解释;
srcText:造成错误的代码;
url:造成错误的文件的URL。
2、Mozilla中XML DOM支持
1)、创建DOM
DOM标准指出,document.implementation对象有个可用的createDocument()方法。Mozilla严格遵循了这个标准,可以这样创建XML DOM:
var oXmlDom = document.implementation.createDocument("","",null);
createDocument()的三个参数分别是文档的命名空间URL,文档元素的标签以及一个文档类型对象(总是为null,因为在Mozilla中还没有对文档类型对象的支持)。
2)、载入XML
Mozilla只支持一个载入数据的方法:load().
Mozilla的XML DOM会在文件完全载入后触发load事件,也就是说必须使用onload事件处理函数来判断DOM何时可用:
oXmlDom.onload = function()
{
 alert("Done");
}
oXmlDom.load("test.xml");
Mozilla的XML DOM不支持loadXML()方法。要将XML字符串解析为DOM,必须使用DOMParser对象:
var oParser = new DOMParser();
var oXmlDom = oParser.parseFromString("<root/>","text/xml");
可以自己的添加loadXML()方法,XML DOM实际的类称为Document,所以添加新方法同使用prototype对象一样容易,然后用DOMParser创建新的XML DOM,原来的文档必须清空其内容,可用while循环来删除所有的文档的子节点,删除所在的子节点后,所有的oXmlDom的子节点必须导入到文档中(使用importNode()方法)并作为子节点添加(使用appendChild()):
Document.prototype.loadXML = function(sXML)
{
 var oParser = new DOMParser();
 var oXmlDom = oParser.parseFromString(sXml,"text/xml");
 
 while(this.firstChild)
 {
  this.removeChild(this.firstChild);
 }

 for(var i = 0;i < oXmlDom.childNodes.length;i++)
 {
  var oNewNode = this.importNode(oXmlDom.childNodes[i],true);
  this.appendChild(oNewNode);
 }
};
3)、获取XML
Mozilla提供了XMLSerializer对象:
var oSerializer = new XMLSerializer();
var sXml = oSerializer.serializeToString(oXmlDom,"text/xml");
serializeToString()为oXmlDom创建了XML代码,它接受要进行序列化的节点和内容类型作为参数。
defineGetter()方法只存在于Mozilla中,为某个特性定义获取函数,也就是说,读取特性时,就会调用这个函数并返回它的结果。例:
var sValue = oXmlNode.nodeValue;  //读
oXmlNode.nodeValue = "New value"; //写
defineGetter()需要两个对数:特性的名称和要调用的函数。
4)、解析错误
要判断是否在XML代码的解析过程中有错误,必须测试文档元素的标签名:
if(oXmlDom.documentElement.tagName != "parsererror")
{

}
else
{
 
}
唯一能获取确切的错误信息的方法是,解析错误信息文本。最简单的方法是使用正则表达式:var reError = />([\s\s]*?)Location:([\s\s]*?)Line Number (\d+),Column(\d+):<sourcetext>([\s\s*?)(?:\-*\^)/;
这段正是表达式抓取了所有XML代码中潜在的信息。第一个捕获性分组获取错误信息,第二个获取文件名,第三个获取行号,第四个获取列号,第五个获取造成错误的源代码(不包含最后的横线和脱字符号)。
3、通用接口
1)、修改DOM创建
第一步是创建IE和Mozilla通用的创建XML DOM对象的方法。最简单的方法是创建伪类,使之可以这样创建XML DOM:
var oXmlDom = new XmlDom();
当然,在XmlDom()构造函数中必须进行浏览器检测:
function XmlDom()
{
 if(window.ActiveXObject)
 {
  
 }
 else if(document.implementation && document.implementation.createDocument)
 {}
 else
 {
  throw new Error("Your browser doesn't support an XML DOM object.");
 }
}
2)、IE分支
对于构造函数的IE部分,只需把createXMLDOM()函数中的代码插进来即可。
3)、Mozilla分支
Mozilla分支的第一步是,用createDocument()方法创建XML DOM对象。再让Mozilla支持readyState特性以及onreadystatechange事件处理函数。
首先,添加readyState特性,并初始化为0;
Document.prototype.readyState = 0;
下面,创建onreadystatechange特性,并初始化为null;
Document.prototype.onreadystatechange = null;
一旦readyState特性发生变化,必须调用onreadystatechange函数。为达到这个目的,最好创建一个方法:
Document.prototype.__changeReadyState__ = function(iReadyState)
{
 this.readyState = iReadyState;
 if(typeof this.onreadystatechange == "runction")
 {
  this.onreadystatechange();
 }
};
影响到readyState特性的两个方法是,loadXML()和load()。
4)、错误处理
最后一步是为Mozilla创建parseError对象。
下面是完整代码:


function XmlDom() {
    if (window.ActiveXObject) {
        var arrSignatures = ["MSXML2.DOMDocument.5.0", "MSXML2.DOMDocument.4.0",
                             "MSXML2.DOMDocument.3.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.__initError__();
               
        oXmlDom.addEventListener("load", function () {
            this.__checkForErrors__();
            this.__changeReadyState__(4);
        }, false);

        return oXmlDom;       
       
    } else {
        throw new Error("Your browser doesn't support an XML DOM object.");
    }
}

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.linepos = -1;
        this.parseError.reason = null;
        this.parseError.srcText = null;
        this.parseError.url = null;
    };
   
    Document.prototype.__checkForErrors__ = function () {

        if (this.documentElement.tagName == "parsererror") {

            var reError = />([\s\S]*?)Location:([\s\S]*?)Line Number (\d+), Column (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/;

            reError.test(this.xml);
           
            this.parseError.errorCode = -999999;
            this.parseError.reason = RegExp.$1;
            this.parseError.url = RegExp.$2;
            this.parseError.line = parseInt(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 i=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);
    };
   
    Node.prototype.__defineGetter__("xml", function () {
        var oSerializer = new XMLSerializer();
        return oSerializer.serializeToString(this, "text/xml");
    });

}

posted @ 2009-09-06 21:03  flora_asp.net  阅读(208)  评论(0编辑  收藏  举报