Javascript中的XML

 /* *******************  以下为未完成的原文,有些地方有误。保留。  ****************** */

在IE7/8中,有了所谓的原生(Native)的XMLHttpRequest。使用该类在IE中创建的对象,与使用ActiveXObject创建的xhr对象相比,前者几乎继承了后者的全部缺点。而且,也许是出于安全方面的考虑,用户不能对该对象属性进行枚举,这点与AXO对象相同,所以用户无法查看其可用的属性和方法;此外,不知道为什么,IE原生XHR对象返回的responseXML,在查看其documentElement的typeof时,返回unknown,但是直接alert(responseXML.documentElement)时,却会显示为null,如果调用selectNodes等方法,会报错提示documentElement为null。而axo创建的xhr,无论IE版本如何,都可以直接使用documentElement作为一个xmlDoc,进行xpath查询等各项操作。另外,提到unknown类型,这个IE的特色,xhr的readyState为1/2时,status也是unknown,但是这个属性除了使用typeof外,不能对它进行任何操作,包括值比较。只有在readyState为3/4的时候,status会成为一个number,才能参与运算。xhr的onreadystatechange,在赋值前和赋值后均为unknown。很纠结。

 

在xhr返回4/200后,我们非常习惯使用responseText。如果有查询方面的需求,一般我们会写一个通用的parseDom方法,将文本转换为dom来处理。对responseXML的使用案例非常之少,就算偶尔用到一些,也往往是基于IE平台,甚至基于本地文件来操作,对ajax方式返回的responseXML几乎没有人去谈及。我想这里有几个原因:一是标准差别迥异,实现通用方法很难;二是JSON的出现,基于js原生对象,不但数据更少,而且可以查询;三是对xml本身的陌生,xml苛刻和繁琐的标准阻碍了它的普及。

 

我对responseXML一直念念不忘的原因,是因为在JSON出现之前,我已经开始采用AJAX + WebService的方式来实现一些需求。WebServiece返回的是标准的XML文档,而且使用.NET平台创建WebService非常容易。但是返回的结果,一个XML文档,如果我使用responseText的话,其实没有任何意义,至少是偏离了这个模式的本意。由于没有找到解决xml跨平台的办法和较好的案例,所以我一直让WebService返回一个类似JSON的文本,客户端用js通过正则提取JSON文本,然后转换为本地对象的方式来进行交互。(未完)

 

/* ******************************  原文保留结束  *********************************** */

 

上面的话中,对IE7/8原生XMLHttpRequest的一些看法有些问题。但是我依然保留我的一个观点,亦即:这个原生的XHR继承了ActiveXObject的XHR的几乎全部缺点。但是出于对AXO将来命运的担忧,我还是建议在IE中使用原生XHR类来创建对象。

其实大概在上文发出后的两三天里,我就找到了IE原生xhr无法正确返回xml对象的原因。问题出在我的WebService + Ajax模式,IE7/8的xhr对象只是无法正确接收soap1.2的xml文档,所以responseXML是null,即使使用AXO创建的xhr对象也存在同样问题。但让人搞不懂的是,IE6,包括ieTester/IE6,都可以正常接收soap1.2。查不到资料。我只能认为,IE7/8更标准了,它们是在返回一个真正的xml,而不是一个标准宽松的dom。

soap1.1/1.2的文本内容,无论是发送的参数还是返回的结果,仅在一个命名空间的不同,其他完全一样。

所以,当使用soap1.1进行通信时,一切都很正常。IE8的xhr返回了一个运行良好的xmlDocument。至于命名空间对查询的约束……几乎没有,用起来还是那么像dom。当然,你可以使用xpath查询……好吧,正像很多人所说的,其实不一定非得用xml,json多好啊……无所谓,我解决了自己的纠结而已。

在FireFox下的xml查询是个很麻烦但是思路很清楚的事情,只要掌握了其中的思路,很快就可以做出简化查询的通用方法。问题的关键就是对命名空间处理的Namespace Resolver委托函数;而这里让我纠结了半天的并不是如何去写一个恰当的委托函数,而是对“直接量”的命名空间如何处理。解决的办法是在FF官网找到的,找到之后我有些哭笑不得:这个委托函数实际就是做一个枚举,比如<nodeName:ns>这样的节点,委托函数是用来告诉查询器,后面的ns对应哪一个命名空间地址。但是<nodeName xmlns="http://www.xxx.com">的ns是什么呢?看一下代码吧:

 

SOAP1.1返回的XML格式
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 3   <soap:Body>
 4     <getSupportCityResponse xmlns="http://WebXml.com.cn/">
 5       <getSupportCityResult>
 6         <string>string</string>
 7         <string>string</string>
 8       </getSupportCityResult>
 9     </getSupportCityResponse>
10   </soap:Body>
11 </soap:Envelope>
12 <!-- 借用地址 http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?op=getSupportCity -->

相应的Resolver函数应该类似于:

针对SOAP1.1的nsResolver
function nsResolver(prefix){
    
switch(prefix){
        
case 'post'
            : 
return 'http://www.w3.org/2003/05/soap-envelope';
        
case 'xsi'
            : 
return 'http://www.w3.org/2001/XMLSchema-instance';
        
case 'xsd'
            : 
return 'http://www.w3.org/2001/XMLSchema';
    }
    
return 'http://WebXml.com.cn/';
}


然后我把它写成了:

YD的淫
function nsResolver(prefix){
    
return {
        post : 'http://www.w3.org/2003/05/soap-envelope',
        xsi : 'http://www.w3.org/2001/XMLSchema-instance',
        xsd : 'http://www.w3.org/2001/XMLSchema'
    }[prefix] || 'http://WebXml.com.cn/';
}

于是有:

FF下给xmlDocument添加selectNodes的xpath查询方法
xml.selectNodes = function(xpath){
    
var result = null
    , evaluator = new XPathEvaluator()
    , _result = evaluator.evaluate(xpath
        , this
        , nsResolver
        , XPathResult.ORDERED_NODE_ITERATOR_TYPE
        , null)
    , ele;
    
if(_result){
        result = [];
        
while(ele = _result.iterateNext())
             result.push(ele);
    }
    _result = ele = null;
    
return result;
}

在线写很累很累,就写到这里吧。

(我认为依然未完)

 

PS1:gnome-editor就是个很好的js编辑器,还支持着色。

PS2:mono开发工具稳定性和调试工具比vs实在差很多,被折磨了一个星期了,依然无法适应。

PS3:不得不承认VS2010很强大,使得WPF非常容易。加之我的coding能力和超凡的悟性,作为第一次SilverLight,中午就把SL上传基本搞定,所以纠结两件事情:1、是否放弃js类库开发。2、是否回到windows平台。3、虽然我以前很痛恨flash,为什么我对sl一点都不排斥呢?

PS4:其实今天我是来打酱油的。

posted @ 2010-05-15 12:03  MKing's Kindom  阅读(238)  评论(0编辑  收藏  举报