关于客户端Javascript中XML解析的总结

前几日阅读了“谷哥”的文章“XPath详解,总结”(原文地址:http://www.cnblogs.com/ktgu/archive/2009/04/16/1353246.html),写得很详细,推荐一下。这里写一点自己的总结,以备日后查阅。

不同浏览器使用xpath解析xml的方式:

function loadXMLDoc(dname) {
    if (window.XMLHttpRequest) {
        xhttp = new XMLHttpRequest();
    }
    else {
        xhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xhttp.open("GET", dname, false);
    try {
        //IE10中AJAX默认返回的xml document不支持selectNodes和selectSingleNode方法,需要在请求前如下设置
        xhttp.responseType = 'msxml-document';
    }
    catch (e) {
    }
    xhttp.send("");
    return xhttp.responseXML;
}

$(function() {
    xml = loadXMLDoc("x4.xml?v=1");
    //    xml.setProperty("SelectionLanguage", "XPath");
    path = "/na:messages/na:message/na:to/na:group/h2:address";
    var nsString = "xmlns:na='http://www.w3.org/ns-0' xmlns:hCCC='http://www.w3.org/ns-2' xmlns:h2='http://www.w3.org/ns-1' xmlns:h3='http://www.w3.org/ns-3'";
    // code for IE
    if (window.ActiveXObject) {
        xml.setProperty("SelectionNamespaces", nsString);

        var nodes = xml.selectNodes(path);

        for (i = 0; i < nodes.length; i++) {
            $("#content").val($("#content").val() + "(" + i + ")----------------------------------------------------------------\r\n" + nodes[i].xml + "\r\n");
        }
    }
    // code for Mozilla, Firefox, Opera, etc.
    else if (document.implementation && document.implementation.createDocument) {
        $("#content").val("");
        function resolver(prefix) {
            switch (prefix) {
                case "hCCC": return "http://www.w3.org/ns-2";
                case "h2": return "http://www.w3.org/ns-1";
                case "h3": return "http://www.w3.org/ns-3";
                case "na": return "http://www.w3.org/ns-0";
            }
        }
//        var resolver = xml.createNSResolver(xml.documentElement)

        try {
            var nodes = xml.evaluate(path, xml, resolver, XPathResult.ANY_TYPE, null);
            var result = nodes.iterateNext();
            var i = 0;
            while (result) {
                $("#content").val($("#content").val() + "(" + i + ")----------------------------------------------------------------\r\n" + result.outerHTML + "\r\n");
                result = nodes.iterateNext();
                i++;
            }
        }
        catch (ex) {
            var a = ex;
        }
    }
});


这里借用一下上文中的XML文档

<?xml version="1.0" encoding="UTF-8"?>
<messages xmlns="http://www.w3.org/ns-0" xmlns:h1="http://www.w3.org/ns-1" 
          xmlns:h2="http://www.w3.org/ns-2" xmlns:h3="http://www.w3.org/ns-3">
  <message id="1">
    <sender>gukaitong@gmail.com</sender>
    <to>
      anonymous@gmail.com
      <group name="IT">
        <h1:address>111@gmail.com</h1:address>
        <address id="3">222@gmail.com</address>
        <h2:address>aaa@gmail.com</h2:address>
        <h3:address>bbb@gmail.com</h3:address>
        <h2:address>ccc@gmail.com</h2:address>
      </group>
    </to>
    <subject>This is a sample</subject>
    <datetime date="2008-12-11" time="12:00:00" formatted="12/11/2008 12:00AM">2008-12-11T12:00:00Z</datetime>
    <body>
      Are you interested in?
    </body>
  </message>
  <message id="2">
    <sender>333@gmail.com</sender>
    <to>444@gmail.com</to>
    <subject>No title</subject>
    <body/>
  </message>
</messages>


上面的例子中,有以下几点需要注意的地方:

1.在请求XML文档时,加入了一句代码“xhttp.responseType = 'msxml-document';”,原因在注释中已经解释得很清楚了;

2.当xml中含有命名空间时,在使用XPath解析前,需要通过一种方式让浏览器知道需要用到的命名空间。当xml文档中含有默认命名空间时,XPath表达式中受默认命名空间限定的节点,也必须显示指明默认命名空间的前缀,前缀定义的方式后面详细说明。

IE中,通过xml文档对象的setProperty方法设置一个命名空间和前缀对应关系的字符串:

var nsString = "xmlns:ns='http://www.w3.org/ns-0' xmlns:hCCC='http://www.w3.org/ns-2' xmlns:h2='http://www.w3.org/ns-1' xmlns:h3='http://www.w3.org/ns-3'";
xml.setProperty("SelectionNamespaces", nsString);

特别注意:当xml中有默认命名空间时,也必须加入到该字符串中,并且可随意起一个前缀,如 xmlns:ns='http://www.w3.org/ns-0'

 

火狐中,给evaluate方法传入一个命名空间解析对象(如果没有命名空间时,传null):

创建命名空间解析对象有两种方式:

一:创建一个接受命名空间前缀作为参数的方法,然后返回对应的命名空间URI

二:使用一个包含命名空间信息的节点,调用xml文档对象的createNSResolver方法来生成一个命名空间解析器

        function resolver(prefix) {
            switch (prefix) {
                case "hCCC": return "http://www.w3.org/ns-2";
                case "h2": return "http://www.w3.org/ns-1";
                case "h3": return "http://www.w3.org/ns-3";
                case "na": return "http://www.w3.org/ns-0";
            }
        }
//        var resolver = xml.createNSResolver(xml.documentElement)
var nodes = xml.evaluate(path, xml, resolver, XPathResult.ANY_TYPE, null);

特别注意:当xml中有默认命名空间时,只有第一种方式有效,此时默认命名空间和前缀的对应关系也需要在方法中指明,前缀可以随便取名,如:case "ns": return "http://www.w3.org/ns-0";  或 default: return "http://www.w3.org/ns-0";
第二种方式经测试无效,我想原因可能就是这种方式无法指明默认命名空间和前缀的对应关系。

 

 

 

posted @ 2014-01-16 16:23  sagatx  阅读(257)  评论(0编辑  收藏  举报