IE中的XML DOM 与 Firefox中的XML DOM 比较

IE中的XML DOM

当微软在 IE 5.0 中第一次加入对 XML 支持时,他们只是在 MSXML ActiveX 库(最初是为了在 IE 4.0 中解析 Active Channels 的组件)中实现 XML 的功能。最初的版本并没有打算公开使用,然而随着开发人员逐渐了解这个组件并尝试使用时,微软才意识到这个库的重要性,很快就在 IE 4.01 中发布了 MSXML 完全升级版本。
MSXML 最初还只是 IE 的一个组件。直到 2001 年,微软发布了 MSXML 3.0 ,这是一个通过其公司网站独立发布的产品。在 2001 年晚些时候,微软又发布了 MSXML 4.0 ,并且将其更名为微软 XML 核心服务组件。 MSXML 从最初一个基本的、无校验功能的 XML 解析器,逐渐发展成一个功能强大的组件,能够校验 XML 文档,进行 XSL 转化,支持命名空间、 XML 的简单 API SAX ),以及 W3C XPath XML Schema 标准,并且每个新版本都在性能上有一定的提升。
为了在 JavaScript 中创建 ActiveX 对象,微软实现一个新的 ActiveXObject 类,该类用来实例化 ActiveX 对象。 ActiveXObject 类的构造函数包含一个字符串参数,该参数表示要创建的 ActiveX 对象的版本,在此指的就是 XML 文档的版本。第一个 XML DOM ActiveX 对象名为 Microsoft.XmlDom ,其创建方法如下所示:
var oXmlDom = new ActiveXObject("Microsoft.XmlDom");
这个新创建的 XML DOM 对象与其他 DOM 对象一样,可以用来遍历 DOM 树,操作 DOM 节点。
到本书截稿为止, MSXML DOM 文档共有五个不同的版本,分别是:
q  Microsoft.XmlDom
q  MSXML2.DOMDocument
q  MSXML2.DOMDocument.3.0
q  MSXML2.DOMDocument.4.0
q  MSXML2.DOMDocument.5.0
MSXML 是基于 ActiveX 的实现,因此只能够在 Windows 平台上使用。在 Mac 平台上的 IE 5 是不提供 XML DOM 支持的。
因为存在五个不同版本,而你总是会使用最新版,所以使用一个函数来判断浏览器所使用的版本是相当有用的。这样就可以确保使用最新的 XML 支持,获取最佳的性能。下面的函数 createDocument() 将使你能够创建正确的 MSXML DOM 文档。
function createDocument() {
    var aVersions = [ "MSXML2.DOMDocument.5.0",
       "MSXML2.DOMDocument.4.0","MSXML2.DOMDocument.3.0",
       "MSXML2.DOMDocument","Microsoft.XmlDom"
    ];
 
      for (var i = 0; i < aVersions.length; i++) {
         try {
             var oXmlDom = new ActiveXObject(aVersions[i]);
             return oXmlDom;
         } catch (oError) {
               // 不做任何处理
      }
    }
    throw new Error("MSXML is not installed.");
}
该函数遍历存放 MSXML DOM 文档的版本号的 aVersions 数组,从最新版本 MSXML2.DOMDocument.5.0 开始尝试创建 DOM 文档。如果成功创建对象,那么返回该对象且退出 createDocument(); 否则 try...catch 语句将捕获所抛出的异常,并继续下一次循环,尝试下一个版本。如果 MSXML DOM 文档创建失败,那么抛出异常,说明 MSXML 未安装。由于该函数不是一个类,所以用法与其他函数类似,都将返回一个值:
var oXmlDom = createDocument();
使用 createDocument() 函数将确保程序使用最新的 DOM 文档。当创建了 XML 文档后,下一步就是载入 XML 数据。
1. IE 中载入 XML 数据
MSXML 支持两种载入 XML 的方法: load() loadXML() Load() 方法从 Web 的指定位置载入一个 XML 文件。与 XMLHttp 一样, load() 方法可以以同步或异步两种模式载入数据。默认情况下, load() 方法 采用异步模式;如果要采用同步模式,那么必须将 MSXML 对象的 async 属性设置为 false ,代码如下:
oXmlDom.async = false;
当采用异步模式时, MSXML 对象公开了 readyState 属性,该属性和 XMLHttp readyState 属性一样,包含五种状态。
此外, DOM 文档支持 onreadystatechange 事件处理函数,可以监控 readyState 属性。因为异步模式是默认选项,因此将 async 属性设置为 true 是可选的:
oXmlDom.async = true;
 
oXmlDom.onreadystatechange = function () {
    if (oXmlDom.readyState == 4) {
       // document 完全载入后,进行某些操作
    }
};
 
oXmlDom.load("myxml.xml");
本示例中,将把虚构的、名为 myxml.xml XML 文档载入到 XML DOM 文档中。当 readyState 值为 4 时,说明文档已经完全载入,则执行 if 语句中的代码。
第二种载入 XML 数据的方法是 loadXML() ,该方法与 load() 方法的主要区别在于从字符串载入 XML ,而不是根据指定的文件名载入 XML 。该字符串必须包含正确格式的 XML ,如下所示:
var sXml = "<root><person><name>Jeremy McPeak</name></person></root>";
 
oXmlDom.loadXML(sXml);
在此, oXmlDom 文档将载入 sXml 变量中包含的 XML 数据。 loadXML() 方法不需要像 load() 方法那样检查 readyState 属性,也不需要设置 async 属性,因为该方法并不涉及服务器请求。
2. IE 中遍历 XML DOM 文档
XML DOM 文档的遍历与 HTML DOM 的遍历非常类似,因为它们都是节点层次的结构。节点树的最顶部是 documentElement 属性,包含文档的根元素。使用表 4-1 中所列出的属性,可以访问文档中任何元素或属性。
4-1 XML DOM 属性
   
   
attributes
包含当前节点属性的数组
childNodes
包含子节点数组
firstChild
指向当前节点的第一个子节点
lastChild
指向当前节点的最后一个子节点
nextSibling
返回当前节点的下一个邻居节点
nodeName
返回当前节点的名字
nodeType
指定当前节点的 XML DOM 节点类型
nodeValue
包含当前节点的文本
ownerDocument
返回文档的根元素
parentNode
指向当前节点的父节点
previousSibling
返回当前节点的前一个邻居节点
text
返回当前节点的内容或当前节点及其子节点的文本(只有 IE 才支持的属性)
xml
以字符串返回当前节点及其子节点的 XML (只有 IE 才支持的属性)
遍历 DOM 文档并获取数据,是一个很直观的过程。让我们看看下面的 XML 文档:
<?xml version="1.0" encoding="utf-8"?>
 
<books>
    <book isbn="0471777781">Professional Ajax</book>
    <book isbn="0764579088">Professional JavaScript for Web Developers</book>
    <book isbn="0764557599">Professional C#</book>
    <book isbn="1861002025">Professional Visual Basic 6 Databases</book>
</books>
这是一个简单的 XML 文档,包含一个根元素 <books/> 以及四个子元素 <book/> 。以该文档为例,我们可以研究 DOM 的细节。 DOM 树是基于节点之间的关系构造的。一个节点可能包含其他节点或者子节点。另一个节点可能与其他节点拥有相同的父节点,我们称之为邻居节点。
如果要获取文档中第一个 <book/> 元素,那么只需简单通过访问 firstChild 属性就可以达到目的:
var oRoot = oXmlDom.documentElement;
 
var oFirstBook = oRoot.firstChild;
documentElement 赋给变量 oRoot ,可以节省程序空间和输入的内容,尽管这并不是必需的。使用 firstChild 属性可以引用根元素 <books/> 的第一个子元素 <books/> 的引用,并将其赋值给变量 oFirstBook
使用 childNodes 集合也可以达到相同的目的:
var oFirstBook2 = oRoot.childNodes[0];
选择 childNodes 集合中的第一项将返回根节点的第一个子节点。因为 childNodes JavaScript 中的 NodeList 类型,所以使用 length 属性可以得到子节点的数量,如下:
var iChildren = oRoot.childNodes.length;
本示例中,因为文档元素有四个子节点,所以 iChildren 值为 4
正如前面所述,节点可以有子节点,也就意味着它可以有父节点。通过 parentNode 属性可以选择当前节点的父节点:
var oParent = oFirstBook.parentNode;
在本小节前面已经提到变量 oFirstBook ,不过很快,它现在已经是文档中第一个 <book/> 元素,所以其 parentNode 属性就是指 DOM documentElement 属性,也就是 <books/> 元素。
如果当前节点是 book 元素,那么如何选择另一个 book 元素呢?因为 <book/> 元素有共同的父节点,所以它们互为邻居关系。通过 nextSibling previousSibling 属性可以选择当前节点的临近节点。 nextSibling 属性指向下一个邻居,而 previousSibling 属性 指向前一个邻居:
var oSecondBook = oFirstBook.nextSibling;
 
oFirstBook2 = oSecondBook.previousSibling;
这段代码引用第二个 <book/> 元素,并将其赋值给 oSecondBook 。通过 oSecondBook 邻居节点对变量 oFirstBook2 重新赋值, oFirstBook2 的值不变。如果节点没有下一个邻居节点,那么 nextSibling null 。对于 previousSibling 也是同样的, 如果当前节点没有前一个邻居节点,那么 previousSibling 也为 null
现在我们知道了如何遍历文档结构,接下来要了解的是如何从树的节点获取数据。例如,使用 text 属性可以得到包含第三个 <book/> 元素的文本,代码如下:
var sText = oRoot.childNodes[2].text;
text 属性(微软特有的属性)可以得到该节点包含的所有文本节点,该属性相当有用。如果没有 text 属性,访问文本节点必须:
var sText = oRoot.childNodes[2].firstChild.nodeValue;
这段代码与前面使用 text 属性的代码一样得到同样的结果。类似上一个例子,使用 childNodes 集合引用第三个 <book/> 元素,而使用 firstChild 指向 <book/> 元素的文本节点,因为文本节点在 DOM 中仍是一个节点。使用 nodeValue 属性获取当前节点的值,就可以获取文本。
这两个示例所产生的结果是相同的,然而使用 text 属性和使用文本节点的 nodeValue 属性之间存在一个主要的区别。 text 属性将得到包含当前元素及其子节点的所有文本节点的值,而 nodeValue 属性只能得到当前节点的值。它虽然是个有用的属性,但可能会返回比预期值更多的内容。例如,假设我们将 XML 文档修改成:
<?xml version="1.0" encoding="utf-8"?>
 
<books>
 
    <book isbn="0471777781">
        <title>Professional Ajax</title>
        <author>Nicholas C. Zakas, Jeremy McPeak, Joe Fawcett</author>
    </book>
    <book isbn="0764579088">Professional JavaScript for Web Developers</book>
    <book isbn="0764557599">Professional C#</book>
    <book isbn="1861002025">Professional Visual Basic 6 Databases</book>
</books>
新的 XML 文档在第一个 <book/> 元素中添加了两个新的子节点: <title/> 元素(书名), <author/> 元素(作者)。我们再一次使用 text 属性 :
alert(oFirstChild.text);
代码中没有其他新的内容,我们可以看看图 4-1 中所显示的结果。
  4-1
请注意,这时我们将获得 <title/> <author/> 元素的文本节点,并将其连接在一起。这就是 text nodeValue 的不同之处。 nodeValue 属性只能得到当前节点的值,而 text 属性则将得到包含当前节点及其子节点的所有文本节点。
MSXML 还提供其他一些获取特定节点或数值的方法,最常用的方法是 getAttribute() getElementsByTagName()
getAttribute() 方法将接受一个包含属性名称的字符串型参数,并返回属性值。如果指定的属性不存在,那么返回的值为 null 。我们还将使用本小节前面提到的那个 XML 文档,请看下列代码:
var sAttribute = oFirstChild.getAttribute("isbn");
 
alert(sAttribute);
这段代码获取第一个 <book/> 元素的 isbn 属性值,并将其赋值给变量 sAttribute 然后使用 Alert() 方法显示该值。
getElementsByTagName() 方法根据其参数所指定的名字,返回子元素的 NodeList 。该方法只搜索给定的节点中的元素,所以返回的 NodeList 不包含任何外部元素。例如:
var cBooks = oRoot.getElementsByTagName("book");
 
alert(cBooks.length);
这段代码获取文档中所有的 <book/> 元素,并将返回的 NodeList 赋值给变量 cBooks 。对于前面那个 XML 文档例子而言,警告框将显示找到的四个 <book/> 元素。如果要获取所有子节点,那么必须用“ * ”作为 getElementsByTagName() 方法的参数,其代码如下所示:
var cElements = oRoot.getElementsByTagName("*");
因为前面的 XML 文档例子中只包含 <book/> 元素,所以这段代码的结果与上一个示例相同。
3. IE 中获取 XML 数据
要获取 XML 数据只需使用一个属性,即 xml 。该属性将对当前节点的 XML 数据进行序列化。 序列化(serialization 是将对象转换成简单的可存储或可传输格式的过程。 xml 属性将 XML 转换成字符串形式,包括完整的标签名称、属性和文本:
var sXml = oRoot.xml;
alert(sXml);
这段代码从文档元素开始序列化 XML 数据,并将其作为参数传递给 alert() 方法。下面就是部分已序列化的 XML
<books><book isbn="0471777781">Professional Ajax</book></books>
已序列化的数据可以载入到另一个 XML DOM 对象,发送到服务器,或者传给另一个页面。通过 xml 属性返回的已序列化 XML 数据,取决于当前节点。如果是在 documentElement 节点使用 xml 属性 ,那么将返回整个文档的 XML 数据;如果只是在 <book/> 元素上使用它,那么将返回该 <book/> 元素所包含的 XML 数据。
xml 属性是只读属性。如果希望往文档中添加元素,那么必须使用 DOM 方法来实现。
4. IE 中操作 DOM
现在为止,我们已经学习如何遍历 DOM ,从 DOM 中提取信息,将 XML 转换成字符串格式。接下来学习的是如何在 DOM 中添加、删除和替换节点。
l   创建节点
使用 DOM 方法可以创建多种不同的节点。第一种就是用 createElement() 方法创建的元素。向该方法传入一个参数,指明要创建的元素标签名称,并返回一个对 XMLDOMElement 的引用:
var oNewBook = oXmlDom.createElement("book");
 
oXmlDom.documentElement.appendChild(oNewBook);
这段代码创建一个新的 <book/> 元素,并通过 appendChild() 方法把它添加到 documentElement 中。 appendChild() 方法添加由其参数指定的新元素,并且将其作为最后一个子节点。但在该例子中,添加到该文档中的是一个空的 <book/> 元素,因而还需要为该元素添加一些文本:
var oNewBook = oXmlDom.createElement("book");
 
 
var oNewBookText = oXmlDom.createTextNode("Professional .NET 2.0 Generics");
 
oNewBook.appendChild(oNewBookText);
 
oXmlDom.documentElement.appendChild(oNewBook);
这段代码通过 createTextNode() 方法创建一个文本节点,并通过 appendChild() 方法把它添加到新创建的 <book/> 元素中。 createTextNode() 方法只有一个字符串参数,用来指定文本节点的值。
现在已经通过程序创建了新的 <book/> 元素,为其提供了一个文本节点,并将它添加到文档中。对于这个新元素而言,还需要像其他邻居节点一样,为其设置 isbn 属性。这很简单,只要通过 setAttribute() 方法就可以创建属性,该方法适用于所有元素节点。
var oNewBook = oXmlDom.createElement("book");
 
var oNewBookText = oXmlDom.createTextNode("Professional .NET 2.0 Generics");
oNewBook.appendChild(oNewBookText);
 
oNewBook.setAttribute("isbn","0764559885");
 
oXmlDom.documentElement.appendChild(oNewBook);
上面这段代码中,新添加的一行是用来创建 isbn 属性的,并将其值赋为 0764559885 setAttribute() 方法有两个参数:第一个参数是属性名,第二个参数则是赋给该属性的值。对于向元素添加属性, IE 还提供其他一些方法,不过它们实际上并不比 setAttribute() 更好用,而且还需要更多的编码。
l   删除、替换和插入节点
如果能够往文档中添加节点,那么同样意味着可以删除节点。 removeChild() 方法正是用来实现该功能的。该方法包含一个参数:要删除的节点。例如,要从文档中删除第一个 <book/> 元素,则可以使用以下代码:
var oRemovedChild = oRoot.removeChild(oRoot.firstChild);
removeChild() 方法返回被删除的子节点,因而 oRemoveChild 变量将指向已删除的 <book/> 元素。当拥有对旧节点的引用时,就可以将其放置在文档的任何地方。
如果想用 oRemovedChild 指向的元素来替换第三个 <book/> 元素,那么可以通过 replaceChild() 方法来实现,该方法返回被替换的节点:
var oReplacedChild = oRoot.replaceChild(oRemovedChild, oRoot.childNodes[2]);
replaceChild() 方法接受两个参数:新添加的节点和将被替换的节点。在这段代码中,将用 oRemovedChild 变量引用的节点替换第三个 <book/> 元素,而被替换节点的引用将存在 oReplacedChild 变量中。
由于 oReplaceChild 变量是被替换节点的引用,因而可以容易地将其插入到文档中。使用 appendChild() 方法可以该其添加到子节点列表的最后,也可以使用 insertBefore() 方法将该节点插入到某个节点之前:
oRoot.insertBefore(oReplacedChild, oRoot.lastChild);
这段代码将之前被替换的节点插入到最后一个 <book/> 元素的前面。 lastChild 属性的用法与 firstChild 选择第一个子节点 非常相似,通过该属性可以获取最后一个子节点。 insertBefore() 方法接受两个参数:要插入的节点和表示插入点的节点(插入点在该节点之前)。该方法也将返回插入节点的值,但上述例子中并不需要。
如你所见, DOM 是一个相当强大的接口,通过它可以实现数据的获取、删除和添加等操作。
5. IE 中处理错误
XML 数据的载入过程中,可能会由于不同的原因而抛出错误。例如,外部的 XML 文件找不到,或者 XML 的格式不正确。为了处理这些情况, MSXML 提供了一个包含错误信息的 parseError 对象。对于每个由 MSXML 创建的 XML DOM 文档对象而言,该对象都是其所属的属性值之一。
我们可以通过 parseError 对象公开的与整数 0 进行比较的 errorCode 属性来检查错误。如果 errorCode 不等于 0 ,则表示有错误发生。下面的例子故意设计出现一个错误。
var sXml = "<root><person><name>Jeremy McPeak</name></root>";
var oXmlDom = createDocument();
oXmlDom.loadXML(sXml);
 
if (oXmlDom.parseError.errorCode != 0) {
    alert("An Error Occurred: " + oXmlDom.parseError.reason);
} else {
    // XML 载入成功后的操作
}
大家会注意到,在突出显示的代码行中, <person> 元素是不完整的(没有相应的 </person> 标签)。由于要载入的 XML 的格式不正确,因此将产生一个错误。然后 errorCode 0 进行比较,如果不相等(在本例中就不相等),那么将显示发生错误的警告。要实现该功能,可以使用 parseError 对象的 reason 属性来获取错误出现的原因。
parseError 对象提供了以下属性,能够帮助你更好地了解错误:
q  errorCode: 错误代码(长整型);
q  filePos: 在文件中发生错误的位置(长整型);
q  line: 包含错误的代码行的行号(长整型);
q  linePos : 在特定行中发生错误的位置(长整型);
q  reason: 错误的原因(字符串型);
q  srcText: 发生错误的代码行内容(字符串型);
q  url: XML 文档的 URL (字符串型)。
尽管这些属性提供了每种错误的信息,但是应该使用哪个属性,则取决于你的需要。
errorCode 属性可以是正数也可以是负数,只有当 errorCode 0 时才表示没有错误发生。

 

Firefox中的XML DOM

现在我们来看看 Firefox 中的 XML DOM 实现, Firefox 的开发人员采用更为标准的方法,将其作为 JavaScript 实现的一部分。 Mozilla 确保所有基于 Gecko 的浏览器的所有平台都支持 XML DOM
Firefox 中创建一个 XML DOM ,需要调用 document.implementation 对象的 createDocument() 方法。该方法接受三个参数:第一个参数是包含文档所使用的命名空间 URI 的字符串;第二个参数是包含文档根元素名称的字符串;第三个参数是要创建的文档类型(也称为 doctype )。如果要创建空的 DOM 文档,则代码如下所示:
var oXmlDom = document.implementation.createDocument("", "", null);
前两个参数是空字符串,第三个参数为 null ,这样可以确保生成一个彻底的空文档。事实上,现在 Firefox 中并不提供针对文档类型的 JavaScript 支持,所以第三个参数总是为 null 。如果要创建包含文档元素的 XML DOM ,那么可以在第二个参数中指定标签名称:
var oXmlDom = document.implementation.createDocument("", "books", null);
这段代码创建了一个 XML DOM ,其 documentElement <books/> 。如果要创建包含指定命名空间的 DOM ,可以在第一个参数中指定命名空间 URI
var oXmlDom = document.implementation.createDocument("http://www.site1.com",
       "books", null);
当在 createDocument() 方法中指定命名空间时, Firefox 会自动附上前缀 a0 以表示 命名空间 URI
<a0:books xmlns:a0="http://www.site1.com" />
接着,你可以通过程序来填充 XML 文档,不过在一般情况下,还需要在空的 XML DOM 对象中载入现有的 XML 文档。
1. Firefox 中载入 XML 数据
Firefox 中,将 XML 载入 XML DOM 的方法和微软采用的方法大致相同,只存在一个显著区别: Firefox 只支持 load() 方法。因此,在这两种浏览器中载入外部 XML 数据的代码是相同的:
oXmlDom.load("books.xml");
与微软的 IE 一样, Firefox 同样实现了 async 属性,该属性的行为也与其一致:将 async 设置为 false ,表示以同步模式载入文档;否则,以异步模式载入文档。
Firefox XML DOM 实现和微软的 XML DOM 实现还存在另一个不同,即 Firefox 不支持 readyState 属性及 onreadystatechange 事件处理函数。在 Firefox 中,支持 load 事件和 onload 事件处理函数。在文档完全载入后将触发 load 事件:
oXmlDom.load("books.xml");
oXmlDom.onload = function () {
    // 文档完全载入后的操作
};
正如前面所说,在 Firefox XML DOM 实现中,并没有 loadXML() 方法,不过通过 Firefox 中的 DOMParser 类可以模拟 loadXML() 的行为。该类有一个名为 parseFromString() 的方法,用来载入字符串并解析成文档:
var sXml = "<root><person><name>Jeremy McPeak</name></person></root>";
var oParser = new DOMParser();
var oXmlDom = oParser.parseFromString(sXml,"text/xml");
在这段代码中,创建了一个 XML 字符串,并作为参数传递给 DOMParser parseFromString() 方法。 parseFromString() 方法的两个参数分别是 XML 字符串和数据的内容类型(一般设置为 text/xml ) parseFromString() 方法返回 XML DOM 对象,因此这里得到的 oXmlDom 与第一个例子相同。
2. Firefox 中获取 XML 数据
尽管存在这样那样的不同,但 IE Firefox 中用于获取文档中 XML 数据的大多数属性和方法是一致的。正如在 IE 中,可以使用 documentElement 属性来获取文档的根元素,例如:
var oRoot = oXmlDom.documentElement;
Firefox 同样支持 W3C 标准属性,包括 childNodes firstChild lastChild nextSibling nodeName nodeType nodeValue ownerDocument parentNode previousSibling 。不幸的是,对于微软专有的 text xml 属性, Firefox 并不支持,不过可以利用其他方法来模拟该属性的行为。
大家应该还记得, text 属性返回了当前节点的内容,或者是当前节点及其子节点的内容。这不仅仅返回当前节点的文本,还有所有子节点的文本,因此要模拟该功能实现是十分容易的。下面这个简单的函数就能够完成该功能,该函数唯一的参数是一个节点:
function getText(oNode) {
    var sText = "";
    for (var i = 0; i < oNode.childNodes.length; i++) {
       if (oNode.childNodes[i].hasChildNodes()) {
           sText += getText(oNode.childNodes[i]);
       } else {
           sText += oNode.childNodes[i].nodeValue;
       }
    }
    return sText;
}
getText() 函数中, sText 变量用来保存获取的所有文本。接着对 oNode 的子节点使用 for 循环 进行遍历,检查每个子节点是否包含子节点。如果有子节点,那么就将其 childNode 传给 getText() 函数,并进行同样的处理;如果没有子节点,那么将当前节点的 nodeValue 加到字符串中(对文本节点而言,这只是文本字符串)。处理了所有子节点后,该函数返回变量 sText
IE 中的 xml 属性将存放对当前节点包含的所有 XML 进行序列化的结果。在 Firefox 中,提供了一个名为 XMLSerializer 对象来完成这一功能。该对象提供一个使用 JavaScript 可访问的 serializeToString() 方法,使用该方法可以对 XML 数据进行序列化。
function serializeXml(oNode) {
    var oSerializer = new XMLSerializer();
    return oSerializer.serializeToString(oNode);
}
serializeXml() 函数以 XML 节点作为参数,创建一个 XMLSerializer 对象,并将该节点传给 serializeToString() 方法。该方法将向调用者返回 XML 数据的字符串表示。
对于节点操作的DOM 方法,Firefox IE 大致相同。参见“在IE 中操作DOM ”小节。
3. Firefox 中处理错误
Firefox IE 的错误处理并不一样。当 IE 遇到错误时,它会填充 parseError 对象;而当 Firefox 遇到错误时,它会将包含错误信息的 XML 文档载入到 XML DOM 文档中。看下面的这个例子:
var sXml = "<root><person><name>Jeremy McPeak</name></root>";
var oParser = new DOMParser();
var oXmlDom = oParser.parseFromString(sXml,"text/xml");
 
if (oXmlDom.documentElement.tagName != "parsererror") {
    // 没有错误发生,进行所需操作
} else {
    alert("An Error Occurred");
}
在突出显示的代码行中,你会发现其中将产生一个错误: XML 字符串格式不正确(因为 <person> 元素不完整,没有相应的 </person> 元素)。当载入错误的 XML 时, XML DOM 对象将会载入一个 documentElement <parsererror/> 的错误文档。我们可以通过检查 documentElement tagName 属性来很容易地确定是否发生错误。如果 tagName 属性不是 parsererror ,就可以确定没有发生任何错误。
在本例中,可能会生成如下所示的错误文档:
<parsererror xmlns="http://www.mozilla.org/newlayout/xml/parsererror.xml">XML
Parsing Error: mismatched tag. Expected: </person>.
Location: [url]http://yoda/fooreader/test.htm[/url]
Line Number 1, Column 43:<sourcetext><root><person><name>Jeremy
McPeak</name></root>
------------------------------------------^</sourcetext></parsererror>
所有的错误信息都包含在错误文档的文本中。如果要通过程序使用这些错误信息,那么首先就要对其进行解析。最简单的方法是使用一个稍长的正则表达式:
var reError = />([\s\S]*?)Location:([\s\S]*?)Line Number (\d+), Column
    (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/;
该正则表达式将错误文档分为五个部分:错误消息、发生错误的文件名、行号、该行中发生错误的位置,以及发生错误的源代码。使用正则表达式对象的 test() 方法可以使用这些信息:
if (oXmlDom.firstChild.tagName != "parsererror") {
    // 没有错误发生,进行所需操作
} else {
    var oXmlSerializer = new XMLSerializer();
    var sXmlError = oXmlSerializer.serializeToString(oXmlDom);
    var reError = />([\s\S]*?)Location:([\s\S]*?)Line Number (\d+), Column
       (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/;
    reError.test(sXmlError);
正则表达式捕获到的第一部分数据是错误消息,第二部分是文件名,第三部分是行号,第四部分是行内位置,第五部分是源码。你可以使用这些解析后的信息来创建自定义的错误消息:
var str = "An error occurred!!\n" +
    "Description: " + RegExp.$1 + "\n" +
    "File: " + RegExp.$2 + "\n" +
    "Line: " + RegExp.$3 + "\n" +
    "Line Position: " + RegExp.$4 + "\n" +
    "Source Code: " + RegExp.$5;
 
alert(str);
如果发生错误,那么 alert() 方法会以易于阅读的格式在警告框中来显示相关的错误信息。

你可能感兴趣的:(xml,IE,dom,休闲)