Ext2.0 与服务端XML的交互(扩展Ext.data.XmlReader )
本文案例如下:后台使用C#写的webservice,返回一个xml串作为结果集。前端需要对xml结果解析,放入到一个表格中。
以前没用Ext的解决办法是 :前台写xsl 转换xml ,把结果放入某个div内。。。优点是灵活多样,缺点是需要手写xsl代码,并对开发人员的dom以及css技术有比较高的要求。
现在有了漂亮贼酷的Ext ,没有理由不选它。 于是用Ext.data.XmlReader 读取服务器传回来的xml,本以为跟读取xml文件一样,读取url就ok了。但是代码一写。问题出现了。
我的代码如下:
alert出来的dataStore.getCount始终是0 。也就是 没有读出来webservice返回的xml串。
仔细查找问题所在。查看了Ext.data.XmlReader类 的源码,看到原来Ext.data.XmlReader 直接使用了 responseXML:
而大家知道webservice返回的responseXML 肯定是一个Xml对象。你的xml串就是被转义并放在 responseXML的根节点的text里的。比如本例:responseXML
对象的 xml 如下:
找到问题后,就考虑解决办法,扩展一下Ext.data.XmlReader。 让它读取responseXML的根节点下的xml串:
把这个js文件引入到页面上,最后把原来第一段代码中的reader定义改为新的xmlreader即可:
在IE 7.0 和 firefox2.0 下测试通过。
以前没用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 });
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);
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/\"><dataset> <results>10</results><item><id>1</id><sex>男</sex><name>JasonWoo</name> <descn>US.Ny</descn></item><item><id>2</id><sex>女</sex><name>Lucy</name><descn>CN.BJ</descn> </item></dataset></string>
可以看到,你想要的string类型的xml串被放在<string>节点里并被转义了,Ext.data.XmlReader并没有读取到你的xml串。<string xmlns=\"http://www.mycompany.com/webservices/\"><dataset> <results>10</results><item><id>1</id><sex>男</sex><name>JasonWoo</name> <descn>US.Ny</descn></item><item><id>2</id><sex>女</sex><name>Lucy</name><descn>CN.BJ</descn> </item></dataset></string>
找到问题后,就考虑解决办法,扩展一下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);
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 下测试通过。