重重的壳裹着轻轻的仰望

I smile when I'm angry. I cheat and I lie. I do what I have to do ··· To get by.

导航

Ext2.0 与服务端XML的交互(扩展Ext.data.XmlReader )

Posted on 2008-04-17 17:54  暴走的猪  阅读(4060)  评论(6编辑  收藏  举报
本文案例如下:后台使用C#写的webservice,返回一个xml串作为结果集。前端需要对xml结果解析,放入到一个表格中。

以前没用Ext的解决办法是 :前台写xsl 转换xml ,把结果放入某个div内。。。优点是灵活多样,缺点是需要手写xsl代码,并对开发人员的dom以及css技术有比较高的要求。
现在有了漂亮贼酷的Ext ,没有理由不选它。 于是用Ext.data.XmlReader 读取服务器传回来的xml,本以为跟读取xml文件一样,读取url就ok了。但是代码一写。问题出现了。
我的代码如下:
 1 
 2 Ext.onReady(function(){ 
 3     var cm = new Ext.grid.ColumnModel([
 4         {header:'编号',dataIndex:'id'},
 5         {header:'性别',dataIndex:'sex'},
 6         {header:'姓名',dataIndex:'name'},
 7         {header:'描述',dataIndex:'descn'}
 8     ]);
 9     cm.defaultSortable = true;
10 
11     var CARTOON_WSDL_ADDR    = "http://localhost/JMAMCCTV/JUUMSystemService/UUMSystemService.asmx";
12 
13     var dataStore = new Ext.data.Store({
14                 url: CARTOON_WSDL_ADDR+'/testXmlpage',
15                 reader: new Ext.data.XmlReader({
16                     totalRecords: "results",
17                     record: "item"
18                 }, [                
19                 { name: "id" },{ name: "sex" },{ name: "name" },{ name: "descn" }
20                 ])
21             });    
22                 
23 
24 
25     var grid = new Ext.grid.GridPanel({
26             renderTo: 'testLayout',
27             ds: dataStore,
28             cm: cm,
29             height:200,
30             width:500
31             title: 'PagerCkp'
32         });
33         
34     dataStore.load({
35         params: {
36             pageindex:1,pageCount:2
37         },
38         callback: function(r, options, success) {
39                 //alert(dataStore.getTotalCount() ); //取得记录总数。即 results 节点中的值
40                 //alert(dataStore.getCount() ); //取得记录数。即 返回的xml中真实的记录数
41             if (success && r.length > 0) {
42                 var ss = r[0].get("id");
43                 //alert(ss);
44             }
45             else{
46             }
47         }
48     })
49 });

alert出来的dataStore.getCount始终是0 。也就是 没有读出来webservice返回的xml串。

仔细查找问题所在。查看了Ext.data.XmlReader类 的源码,看到原来Ext.data.XmlReader 直接使用了 responseXML:
 
1   var doc = response.responseXML;
2         if(!doc) {
3             throw {message: "XmlReader.read: XML Document not available"};
4         }
5         return this.readRecords(doc);

而大家知道webservice返回的responseXML 肯定是一个Xml对象。你的xml串就是被转义并放在 responseXML的根节点的text里的。比如本例:responseXML
对象的 xml 如下:
<?xml version=\"1.0\"?>
<string xmlns=\"http://www.mycompany.com/webservices/\">&lt;dataset&gt&lt;results&gt;10&lt;/results&gt;&lt;item&gt;&lt;id&gt;1&lt;/id&gt;&lt;sex&gt;男&lt;/sex&gt;&lt;name&gt;JasonWoo&lt;/name&gt; &lt;descn&gt;US.Ny&lt;/descn&gt;&lt;/item&gt;&lt;item&gt;&lt;id&gt;2&lt;/id&gt;&lt;sex&gt;女&lt;/sex&gt;&lt;name&gt;Lucy&lt;/name&gt;&lt;descn&gt;CN.BJ&lt;/descn&gt; &lt;/item&gt;&lt;/dataset&gt;</string>
可以看到,你想要的string类型的xml串被放在<string>节点里并被转义了,Ext.data.XmlReader并没有读取到你的xml串。
找到问题后,就考虑解决办法,扩展一下Ext.data.XmlReader。 让它读取responseXML的根节点下的xml串:
  1 /**//**
  2  * @author punkChen
  3  */
  4  
  5  //先对xml对象进行封装。因为很遗憾没有找到ext对其的封装。哪位朋友找到后可以告知。
  6 function XmlDoc()
  7 {
  8     var tXmlDoc = false;
  9     if(window.ActiveXObject)
 10     {
 11         var tMsXmlDomType = ["Msxml2.DOMDocument.5.0""Msxml2.DOMDocument.4.0""Msxml2.DOMDocument.3.0""MSXML2.DOMDocument""MSXML.DOMDocument""Microsoft.XMLDOM"];
 12         for(var i=0;i<tMsXmlDomType.length;i++)
 13         {
 14             try
 15             {
 16                 tXmlDoc = new ActiveXObject(tMsXmlDomType[i]);
 17                 tXmlDoc.setProperty("SelectionLanguage""XPath");
 18                 break;
 19             }
 20             catch(ex){}
 21         }    
 22     }
 23     else if(document.implementation && document.implementation.createDocument)
 24     {
 25         tXmlDoc = document.implementation.createDocument("","",null);     
 26         // for safari,opera
 27         if(!tXmlDoc.load)
 28         { 
 29             tXmlDoc.async = true;
 30             tXmlDoc.hp = new XMLHttpRequest();
 31             tXmlDoc.onload = function(){};
 32             tXmlDoc.hp.hpOwner = tXmlDoc;
 33             tXmlDoc.hp.onreadystatechange = function()
 34             {
 35                 if (tXmlDoc.hp.readyState == 4)
 36                 {
 37                     var _result = tXmlDoc.hp.responseXML;          
 38                     tXmlDoc.onload(_result);   
 39                 }
 40             }
 41             tXmlDoc.hp.load = function(sUrl)
 42             {      
 43                 try
 44                 { 
 45                     this.open("GET", sUrl, this.hpOwner.async);
 46                     this.send(null);     
 47                 }
 48                 catch(ex)
 49                 {
 50                     throw "you can't connect the page using different domain,if you not config the Server-Side code";
 51                 }
 52                 if (!this.hpOwner.async)
 53                 {
 54                     var _result = this.responseXML;
 55                     while (this.hpOwner.hasChildNodes())
 56                         this.hpOwner.removeChild(this.hpOwner.lastChild);           
 57                     for (var i = 0; i < _result.childNodes.length; i++
 58                     {
 59                         this.hpOwner.appendChild(this.hpOwner.importNode(_result.childNodes[i], true));
 60                     }
 61                 }
 62             }    
 63             tXmlDoc.load = function(sUrl)
 64             {
 65                   tXmlDoc.hp.load(sUrl);
 66             }      
 67         }        
 68         // apply to ie
 69         tXmlDoc.onreadystatechange = function(){};    
 70         tXmlDoc.readyState = 4;  // because other browers not this property
 71         tXmlDoc.onload = function(s)
 72         {    
 73             if(tXmlDoc.hp)
 74             {
 75                 var _result = s;
 76                 while (this.hasChildNodes())
 77                     this.removeChild(this.lastChild);           
 78                 for (var i = 0; i < _result.childNodes.length; i++
 79                 {
 80                     this.appendChild(this.importNode(_result.childNodes[i], true));
 81                 }       
 82             }
 83             this.readyState = 4;
 84             this.onreadystatechange(s);
 85         }      
 86         //apply load xml string funciton
 87         tXmlDoc.loadXML = function (s) 
 88         {   
 89             var doc2 = (new DOMParser()).parseFromString(s, "text/xml");  
 90             var roottag = doc2.documentElement;
 91             if ((roottag.tagName == "parserError"|| (roottag.namespaceURI == "http://www.mozilla.org/newlayout/xml/parsererror.xml"))
 92             {
 93                 var _sourceText = roottag.lastChild.firstChild.nodeValue;
 94                 throw ("load XML by string happen error,error detail:\n" + roottag.firstChild.nodeValue+"\n"+_sourceText);
 95                 return false;
 96             }    
 97             while (this.hasChildNodes())
 98                 this.removeChild(this.lastChild);           
 99             for (var i = 0; i < doc2.childNodes.length; i++
100             {
101                 this.appendChild(this.importNode(doc2.childNodes[i], true));
102             }
103             this.onreadystatechange();     
104         }
105     }
106     if(!tXmlDoc)
107     {
108         throw ("Can not create xml doc object!");
109     }
110     return tXmlDoc;
111 }
112 
113 
114 //扩展Ext.data.XmlReader
115 Ext.data.XmlReaderExForService = Ext.extend(Ext.data.XmlReader, {
116 
117     read : function(response){
118         var tmpdoc = response.responseXML;
119         if(!tmpdoc) {
120             throw {message: "XmlReader.read: XML Document not available"};
121         }
122                 
123         var doc = new XmlDoc();
124         
125         if(window.ActiveXObject){
126             doc.loadXML(tmpdoc.text);
127         }
128         else{
129             doc.loadXML(tmpdoc.firstChild.textContent);
130         }
131         if(!doc) {
132             throw {message: "XmlReader.read: XML Document not available"};
133         }
134         return this.readRecords(doc);
135     },
136 
137     
138     readRecords : function(doc){
139         
140         this.xmlData = doc;
141         var root = doc.documentElement || doc;
142         var q = Ext.DomQuery;
143         var recordType = this.recordType, fields = recordType.prototype.fields;
144         var sid = this.meta.id;
145         var totalRecords = 0, success = true;
146         if(this.meta.totalRecords){
147             totalRecords = q.selectNumber(this.meta.totalRecords, root, 0);
148         }
149 
150         if(this.meta.success){
151             var sv = q.selectValue(this.meta.success, root, true);
152             success = sv !== false && sv !== 'false';
153         }
154         var records = [];
155         var ns = q.select(this.meta.record, root);
156         for(var i = 0, len = ns.length; i < len; i++) {
157             var n = ns[i];
158             var values = {};
159             var id = sid ? q.selectValue(sid, n) : undefined;
160             for(var j = 0, jlen = fields.length; j < jlen; j++){
161                 var f = fields.items[j];
162                 var v = q.selectValue(f.mapping || f.name, n, f.defaultValue);
163                 v = f.convert(v, n);
164                 values[f.name] = v;
165             }
166             var record = new recordType(values, id);
167             record.node = n;
168             records[records.length] = record;
169         }
170 
171         return {
172             success : success,
173             records : records,
174             totalRecords : totalRecords || records.length
175         };
176     }
177 });
178 
179 Ext.reg('xmlreaderexfor', Ext.data.XmlReaderExForService);

把这个js文件引入到页面上,最后把原来第一段代码中的reader定义改为新的xmlreader即可:
reader: new Ext.data.XmlReaderExForService

在IE 7.0 和 firefox2.0 下测试通过。