转自:http://www.duduwolf.com/wiki/2007/310.html
javacript中对xml dom的支持,与其他任何特性一样面临着浏览器兼容问题。
一 IE中的XML DOM
1.微软通过ActiveX的MSXML库提供了支持,通过:
<!---->
var
oXmlDom
=
new
ActiveXObject(
"
MSXML2.DOMDocument.5.0
"
)
得到一个XML DOM对象,这是在IE6中的,如果你的IE是更老版本的,可以使用下面的函数得到,如果你没有安装MSXML,将不能得到:
<!---->
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) {
//
ignore
}
}
throw
new
Error(
"
你的系统没有安装MSXML
"
);
}
当然,如果你使用prototype库,可以使用Try.these函数。
2.XML DOM对象可以通过load和loadXML方法载入xml文件或者字符串:
<!---->
oXmlDom.load(
"
test.xml
"
);
oXmlDom.loadXML(
"
<root></root>
"
);
然后这个oXmlDom就可以使用所有的DOM对象方法,比如documentElement.tagName,参见:
《javascript之DOM技术(一)》
《javascript之dom技术(二)》
3.XML DOM默认是通过异步载入xml文件的,可以通过设置async值来选择是同步还是异步:
<!---->
oXmlDom.async
=
true
;
4. IE的XML DOM拥有一个readyState值用来表示载入文件的状态:
0——准备载入
1——正在载入
2——载入完成
3——载入完成并可用,但有一部分数据也许不可用
4——完全载入,完全可用。
相应的有一个onreadystatechange事件,当状态改变时发生,我们可以通过监听此事件来判断XML DOM对象的可用性
<!---->
oXmlDom.onreadystatechange
=
function
() {
if
(oXmlDom.readyState
==
4
) {
alert(
"
load test.xml done!
"
);
alert(
"
Tag name of the root element is
"
+
oXmlDom.documentElement.tagName);
alert(
"
The root element has this many children:
"
+
oXmlDom.documentElement.childNodes.length);
}
};
5.IE的XML DOM对象有一个xml属性,用来返回xml文件的字符串形式,比如
<!---->
oXmlDom.async
=
false
;
oXmlDom.load(
"
test.xml
"
);
alert(oXmlDom.xml);
alert出:<root><child/><child/></root>
6.IE,当载入的XML文件或者字符串解析错误时,将产生一个parseError对象,我们在下面的代码中演示此对象的属性:
<!---->
oXmlDom.async
=
false
;
oXmlDom.load(
"
errors.xml
"
);
//
0表示没有错误
if
(oXmlDom.parseError
!=
0
) {
var
oError
=
oXmlDom.parseError;
alert(
"
An error occurred:\n错误代码:
"
+
oError.errorCode
+
"
\n
"
+
"
行数:
"
+
oError.line
+
"
\n
"
+
"
列数:
"
+
oError.linepos
+
"
\n
"
+
"
原因:
"
+
oError.reason);
}
二.Mozilla的XML DOM对象
1.XML DOM对象的创建,符合DOM标准的,通过document.implementation.createDocument()方法。比如:
<!---->
var
oXmlDom
=
document.implementation.createDocument(
""
,
""
,
null
);
这三个参数分别是文档命名空间、文档元素的标签名以及一个文档类型对象(总为null),比如:
<!---->
var
oXmlDom
=
document.implementation.createDocument(
"
http://www.rubyeye.net
"
,
"
root
"
,
null
);
这段代码创建了一个<a0:root xmlns="http://www.rubyeye.net"/>的XML DOM对象
2.载入xml,Mozilla与IE不同的是只提供了一个load()方法用于载入xml文件,没有提供loadXML()方法用于载入XML字符串。同步载入XML文件的代码与IE相同:
<!---->
oXmlDom.async
=
false
;
oXmlDom.load(
"
test.xml
"
);
异步载入稍有不同,因为Mozilla并不支持readyState属性,并且没有onreadystatechange事件,它只有一个onload的事件,当载入完成时触发;或者说相当于IE的readyState属性等于4的状态。
<!---->
oXmlDom.onload
=
function
(){
alert(
"
done
"
);
}
oXmlDom.load(
"
test.xml
"
);
要将XML字符串解析为DOM对象,必须使用DOMParser对象:
<!---->
var
oParser
=
new
DOMParser();
var oXmlDom=oParser.parseFromString(
"
<root><child/></root>,
"
text
/
xml
"
);
两个参数:要解析的XML字符串以及字符串的内容类型(只能为text/xml或者application/xml)。
不过我们可以实现自己的loadXML方法:
<!---->
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.Mozilla没有提供IE的xml属性来返回XML文档内容,只能通过使用XMLSerializer对象:
<!---->
var
oSerializer
=
new
XMLSerializer();
var
sXml
=
oSerializer.serializeToString(oXmlDom,
"
text/xml
"
);
同样两个参数:XML DOM对象以及转化成的文档类型。
同样,我们也可以给Mozilla的XML DOM对象定义一个属性xml,通过defineGetter方法:
<!---->
Node.prototype.__defineGetter__(
"
xml
"
,
function
(){
var
oSerializer
=
new
XMLSerializer();
var
sXml
=
oSerializer.serializeToString(
this
,
"
text/xml
"
);
});
以后就可以以IE的方式,oXmlDom.xml来获取XML文档内容。
4。错误处理,同样与IE不同,Mozilla当解析错误时会返回一段代码,以标签<prasereoor>包括其中的代码解释了错误发生的原因以及位置等信息,我们只有通过正则表达式解析此段代码,提取错误信息。
<!---->
var
reError
=
/>
([\s\S]
*?
)Location:([\s\S]
*?
)Line Number (\d
+
), Column (\d
+
):
<
sourcetext
>
([\s\S]
*?
)(
?
:\
-*
\
^
)
/
;
//
返回代码的标签名为parsererror,表示错误发生
if
(oXmlDom.documentElement.tagName
==
"
parsererror
"
) {
reError.test(oXmlDom.xml);
alert(
"
An error occurred:\n描述:
"
+
RegExp.$
1
+
"
\n
"
+
"
文件名:
"
+
RegExp.$
2
+
"
\n
"
+
"
行数:
"
+
RegExp.$
3
+
"
\n
"
+
"
列数:
"
+
RegExp.$
4
+
"
\n
"
+
"
原因:
"
+
RegExp.$
5
);
}
三,提供一个跨浏览器的XML DOM对象解决方案,来自于《javascript高级程序设计》
<!---->
function
XmlDom() {
//
通过对象/属性检测法,判断是IE来是Mozilla
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
);
//
创建Mozilla版本的parseError对象
oXmlDom.parseError
=
{
valueOf:
function
() {
return
this
.errorCode; },
toString:
function
() {
return
this
.errorCode.toString() }
};
//
初始化parseError对象
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.
"
);
}
}
//
此处用到了该书中一个浏览器系统检测js文件,如果是Mozilla
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();
}
};
//
初始化parseError对象
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
;
}
};
//
定义Mozilla的loadXML方法
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__();
//
没有问题,设置readyState属性为4
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
"
);
});
}