1 2 /** 3 * @name CeL file function for XML 4 * @fileoverview 5 * 本檔案包含了處理 XML file 的 functions。 6 * @since 7 */ 8 9 10 11 if (typeof CeL === 'function') 12 CeL.setup_module('data.XML', 13 function(library_namespace, load_arguments) { 14 15 // nothing required 16 17 18 /** 19 * null module constructor 20 * @class XML 操作相關之 function。 21 */ 22 CeL.data.XML 23 = function() { 24 // null module constructor 25 }; 26 27 /** 28 * for JSDT: 有 prototype 才會將之當作 Class 29 */ 30 CeL.data.XML 31 .prototype = { 32 }; 33 34 35 36 37 38 /* parse XML document 39 http://www.adp-gmbh.ch/web/js/msxmldom/methods_properties.html 40 http://www.w3pop.com/learn/view/doc/transform_XML/ 41 http://www.vacant-eyes.jp/Tips/txml/030.aspx 42 http://www.klstudio.com/post/94.html 43 http://xmljs.sourceforge.net/ 44 ajaxslt http://code.google.com/p/ajaxslt/ 45 46 flag: dcba in binary 47 isFP: 48 a==0 view as text 49 a==1 view as filename If you want to parse a local file, You can use XSLT as well. 50 rX: 51 b==0 return dom.documentElement object 52 b==1 return dom object 53 fast: 54 c==0 normal speed 55 c==1 faster: ignore check 56 57 to use: 58 filtered_node=return_nodes.selectSingleNode("/tag1/tag2[tag3='1041']") 59 nodes.selectSingleNode("~").Text; 60 nodes.item(0).text; 61 node.getAttribute("~"); 62 node.attributes(0).firstChild.nodeValue.valueOf() 63 node.attributes.item(0).firstChild.nodeValue.valueOf() 64 node.attributes.getNamedItem("~").nodeValue.valueOf() 65 .. 66 67 getXML(): 68 loadXML(getU('全省空白價目表.xml')).getElementsByTagName("Worksheet").length 69 70 71 TODO: 72 可參考 JKL.ParseXML, http://doctype.googlecode.com/svn/trunk/goog/dom/xml.js 73 postXML()和parseXML(text/HTML object/array)方法 74 MSXML2.XSLTemplate 75 76 libXmlRequest Library 77 r=document.implementation.createDocument("",XMLtext,null); 78 r.appendChild(r.createElement(XMLtext)); 79 80 81 string = (new XMLSerializer()).serializeToString(xmlobject); 82 83 */ 84 function loadXML(XMLtext,flag){ 85 var dom//,xmlDoc 86 ,isFP=flag%2,rX,fast; 87 88 if(window.DOMParser){ 89 dom=(new DOMParser).parseFromString(XMLtext,'text/xml');//'application/xml' 90 if(!dom.documentElement||dom.documentElement.tagName=='parsererror') 91 throw new Error(1,dom.documentElement.firstChild.data+'\n'+dom.documentElement.firstChild.nextSibling.firstChild.data); 92 return dom; 93 } 94 95 if(typeof ActiveXObject==='undefined'){ 96 dom=document.createElement('div'); 97 dom.innerHTML=XMLtext; 98 return dom; 99 } 100 101 try{ // ActiveXObject is supported 102 // フリースレッド DOM ドキュメントを使用すれば、ファイルを共有アプリケーション状態に取り込むことができます。 103 // フリースレッド モデルの欠点の 1 つは、未使用のメモリのクリーンアップにおける待ち時間が増大し、それ以降の操作のパフォーマンスに影響を及ぼすということです (実際にはクリーンアップが遅れているだけなのに、これをメモリ リークとして報告してくる人もいます)。 104 // http://www.microsoft.com/japan/msdn/columns/xml/xml02212000.aspx 105 dom=new ActiveXObject("Microsoft.FreeThreadedXMLDOM"); 106 }catch(e){ 107 dom=new ActiveXObject("Microsoft.XMLDOM");//CreateObject("Microsoft.XMLDOM"); MSXML3.DOMDocument,MSXML2.DOMDocument,MSXML.DOMDocument, Msxml2.DOMDocument.6.0,Msxml2.DOMDocument.5.0,Msxml2.DOMDocument.4.0,MSXML4.DOMDocument,Msxml2.DOMDocument.3.0 108 } 109 110 if(!dom)throw new Error(1,'No parser!'); 111 112 flag>>=1;rX=flag%2;flag>>=1;fast=flag%2; 113 114 // faster: 既定の 「レンタル」 スレッディング モデルを使用する方法です (このスレッディング モデルでは、DOM ドキュメントは一度に 1 つのスレッドからしか使用できません)。 115 // http://www.microsoft.com/japan/msdn/columns/xml/xml02212000.aspx 116 if(fast)with(dom)validateOnParse=resolveExternals=preserveWhiteSpace=false; 117 118 if(isFP){ 119 dom.async=false;//'false' 120 //dom.validateOnParse=true; // DTD Validation 121 dom.load(XMLtext); 122 }else dom.loadXML(XMLtext); 123 //if(Number(dom.parseError))throw dom.parseError; // or return null 124 return rX?dom:dom.documentElement; // with(dom.parseError)errorCode,reason,line 125 } 126 127 /* untested 128 TODO: 129 (new XSLTProcessor()).importStylesheet(XMLF); libXmlRequest Library 130 */ 131 //applyXSLT[generateCode.dLK]='loadXML'; 132 function applyXSLT(XMLF, XSLTF) { 133 return loadXML(XSLTF, 1 + 2).transformNode(loadXML(XSLTF, 1 + 2)); 134 }; 135 136 137 138 /* 139 to use: include in front: 140 way1(good: 以reg代替functionPath!): 141 // [function.js]_iF 142 // [function.js]End 143 144 way2(old): 145 // [function.js]getU,functionPath,'eval(getU(functionPath));' 146 // [function.js]End 147 148 old: 149 function getU(p){var o;try{o=new ActiveXObject('Microsoft.XMLHTTP');}catch(e){o=new XMLHttpRequest();}if(o)with(o){open('GET',p,false),send(null);return responseText;}} 150 */ 151 152 153 154 /* JScript or .wsh only, 能 encode 155 http://neural.cs.nthu.edu.tw/jang/books/asp/getWebPage.asp?title=10-1%20%E6%8A%93%E5%8F%96%E7%B6%B2%E9%A0%81%E8%B3%87%E6%96%99 156 */ 157 function getPage(p,enc,t){ // page url, encode, POST text 158 try{ 159 var X=new ActiveXObject('Microsoft.XMLHTTP'),AS; // may error 160 X.open(t?'POST':'GET',p,false); 161 X.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); // POST need this 162 X.send(t||null); // Download the file 163 with(AS=new ActiveXObject("ADODB.Stream")){ 164 Mode=3, // 可同時進行讀寫 165 Type=1, // 以二進位方式操作 166 Open(), // 開啟物件 167 Write(X.responseBody), // 將 binary 的資料寫入物件內 may error 168 Position=0, 169 Type=2; // 以文字模式操作 170 if(enc)Charset=enc; // 設定編碼方式 171 X=ReadText(); // 將物件內的文字讀出 172 } 173 AS=0;//AS=null; // free 174 return X; 175 }catch(e){ 176 //sl('getPage: '+e.message); 177 }} 178 179 180 181 /* set a new XMLHttp 182 Ajax程式應該考慮到server沒有回應時之處置 183 184 return new XMLHttpRequest(for Ajax, Asynchronous JavaScript and XML) controller 185 http://www.xulplanet.com/references/objref/XMLHttpRequest.html 186 http://zh.wikipedia.org/wiki/AJAX 187 http://jpspan.sourceforge.net/wiki/doku.php?id=javascript:xmlhttprequest:behaviour 188 http://www.scss.com.au/family/andrew/webdesign/xmlhttprequest/ 189 http://developer.apple.com/internet/webcontent/xmlhttpreq.html 190 http://www.klstudio.com/catalog.asp?cate=4 191 http://wiki.moztw.org/index.php/AJAX_%E4%B8%8A%E6%89%8B%E7%AF%87 192 http://www.15seconds.com/issue/991125.htm 193 http://www.xmlhttp.cn/manual/xmlhttprequest.members.html 194 http://www.blogjava.net/eamoi/archive/2005/10/31/17489.html 195 http://www.kawa.net/works/js/jkl/parsexml.html 196 http://www.twilightuniverse.com/ 197 198 XMLHttp.readyState 所有可能的值如下: 199 0 還沒開始 200 1 讀取中 Sending Data 201 2 已讀取 Data Sent 202 3 資訊交換中 interactive: getting data 203 4 一切完成 Completed 204 205 XMLHttp.responseText 會把傳回值當字串用 206 XMLHttp.responseXML 會把傳回值視為 XMLDocument 物件,而後可用 JavaScript DOM 相關函式處理 207 IE only(?): 208 XMLHttp.responseBody 以unsigned array格式表示binary data 209 try{responseBody=(new VBArray(XMLHttp.responseBody)).toArray();}catch(e){} 210 http://aspdotnet.cnblogs.com/archive/2005/11/30/287481.html 211 XMLHttp.responseStream return AdoStream 212 */ 213 function newXMLHttp(enc,isText){ 214 //if(typeof XMLHttp=='object')XMLHttp=null; 215 var _new_obj_XMLHttp; 216 if(typeof newXMLHttp.objId=='string')_new_obj_XMLHttp=new ActiveXObject(newXMLHttp.objId); // speedy 217 // jQuery: Microsoft failed to properly implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available. 218 else if(typeof ActiveXObject!='undefined')for(var i=0,a=['Msxml2.XMLHTTP','Microsoft.XMLHTTP','Msxml2.XMLHTTP.4.0'];i<a.length;i++) 219 try{_new_obj_XMLHttp=new ActiveXObject(a[i]);newXMLHttp.objId=a[i];break;}catch(e){}//'Msxml2.XMLHTTP.6.0','Msxml2.XMLHTTP.5.0','Msxml2.XMLHTTP.4.0','Msxml2.XMLHTTP.3.0',["MSXML2", "Microsoft", "MSXML"].['XMLHTTP','DOMDocument'][".6.0", ".4.0", ".3.0", ""] 220 // 或直接設定: XMLHttpRequest=function(){return new ActiveXObject(newXMLHttp.objId);} 221 // 皆無:use XMLDocument. The document.all().XMLDocument is a Microsoft IE subset of JavaScript. http://www.bindows.net/ http://www.java2s.com/Code/JavaScriptReference/Javascript-Properties/XMLDocument.htm 222 else if(typeof window=='object'&&window.XMLHttpRequest/* && !window.ActiveXObject*/){//typeof XMLHttpRequest!='undefined' 223 _new_obj_XMLHttp=new XMLHttpRequest(); 224 // 有些版本的 Mozilla 瀏覽器在伺服器送回的資料未含 XML mime-type 檔頭(header)時會出錯。為了避免這個問題,你可以用下列方法覆寫伺服器傳回的檔頭,以免傳回的不是 text/xml。 225 // http://squio.nl/blog/2006/06/27/xmlhttprequest-and-character-encoding/ 226 // http://www.w3.org/TR/XMLHttpRequest/ search encoding 227 if(_new_obj_XMLHttp.overrideMimeType) 228 _new_obj_XMLHttp.overrideMimeType('text/'+(isText?'plain':'xml')+(enc?'; charset='+enc:''));//oXML 229 } 230 return _new_obj_XMLHttp; 231 } 232 233 /* 讀取URL by XMLHttpRequest 234 235 * 若有多行程或為各URL設定個別XMLHttp之必要,請在一開始便設定getURL.multi_request,並且別再更改。 236 ** 在此情況下,單一URL仍只能有單一個request! 237 ** 設定 dealFunction 須注意程式在等待回應時若無執行其他程式碼將自動中止! 238 可設定: 239 while(getURL.doing)WScript.Sleep(1); //||timeout 240 241 arguments f:{ 242 URL:'', // The same origin policy prevents document or script loaded from one origin, from getting or setting properties from a of a document from a different origin.(http://www.mozilla.org/projects/security/components/jssec.html#sameorigin) 243 enc:'UTF-8', // encoding: big5, euc-jp,.. 244 fn:(dealFunction), // onLoad:function(){}, 245 method:'GET', // POST,.. 246 sendDoc:'text send in POST,..' 247 async:ture/false, // true if want to asynchronous(非同期), false if synchronous(同期的,會直到readyState==4才return) http://jpspan.sourceforge.net/wiki/doku.php?id=javascript:xmlhttprequest:behaviour 248 user:'userName', 249 passwd:'****', // password 250 251 //TODO: 252 parameters:'~=~&~=~', // {a:1,b:2} 253 header:{contentType:'text/xml'}, 254 contentType:'text/xml', 255 run:true/false, // do eval 256 update:DOMDocument, // use onLoad/onFailed to 加工 return text. onFailed(){throw;} will about change. 257 interval:\d, 258 decay:\d, // wait decay*interval when no change 259 maxInterval::\d, 260 //insertion:top/bottom,.. 261 onFailed:function(error){this.status;}, // onFailed.apply(XMLHttp,[XMLHttp.status]) 262 onStateChange:function(){}, 263 } 264 265 266 dealFunction: 267 自行處理 typeof dealFunction=='function': 268 function dealFunction(error){..} 269 代為處理 dealFunction=[d_func,0: responseText,1: responseXML]: 270 responseXML: http://msdn2.microsoft.com/en-us/library/ms757878.aspx 271 function d_func(content,head[,XMLHttp,URL]){ 272 if(head){ 273 // content,head各為XMLHttp.responseText內容及XMLHttp.getAllResponseHeaders(),其他皆可由XMLHttp取得。 274 }else{ 275 // content為error 276 } 277 } 278 e.g., the simplest: [function(c,h){h&&alert(c);}] 279 280 ) 281 */ 282 //getURL[generateCode.dLK]='newXMLHttp'; 283 function getURL(f){ // (URL,fn) or flag URL,dealFunction,method,sendDoc,asyncFlag,userName,password 284 var _f=arguments.callee; 285 if(typeof _f.XMLHttp=='object'){ 286 //try{_f.XMLHttp.abort();}catch(e){} 287 _f.XMLHttp=null; // 此時可能衝突或lose?! 288 } 289 // 處理 arguments 290 if(!(f instanceof Object))a=arguments,f={URL:f,fn:a[1],method:a[2],sendDoc:a[3]}; 291 292 if(!f.URL||!(_f.XMLHttp=newXMLHttp(f.enc,!/\.x(ht)?ml$/i.test(f.URL))))return;//throw 293 //try{_f.XMLHttp.overrideMimeType('text/xml');}catch(e){} 294 if(typeof f.async!='boolean') 295 // 設定f.async 296 f.async=f.fn?true:false; 297 else if(!f.async)f.fn=null; 298 else if(!f.fn) 299 if(typeof _f.HandleStateChange!='function'||typeof _f.HandleContent!='function') 300 // 沒有能處理的function 301 return;//throw 302 else 303 f.fn=_f.HandleContent;//null; 304 if(/*typeof _f.multi_request!='undefined'&&*/_f.multi_request){ 305 if(!_f.q)_f.i={},_f.q=[]; // queue 306 _f.i[f.URL]=_f.q.length; // ** 沒有考慮到 POST 時 URL 相同的情況! 307 _f.q.push({uri:f.URL,XMLHttp:_f.XMLHttp,func:f.fn,start:_f.startTime=new Date}) 308 }else if(_f.q&&typeof _f.clean=='function')_f.clean(); 309 310 // for Gecko Error: uncaught exception: Permission denied to call method XMLHttpRequest.open 311 if(f.URL.indexOf('://')!=-1&&typeof netscape=='object') 312 if(_f.asked>2){_f.clean(f.URL);return;} 313 else try{ 314 if(typeof _f.asked=='undefined') 315 _f.asked=0,alert('我們需要一點權限來使用 XMLHttpRequest.open。\n* 請勾選記住這項設定的方格。'); 316 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); 317 }catch(e){_f.asked++;_f.clean(f.URL);return;}//UniversalBrowserAccess 318 319 //if(isNaN(_f.timeout))_f.timeout=300000;//5*60*1000; 320 with(_f.XMLHttp)try{ // IE:404會throw error, timeout除了throw error, 還會readystatechange; Gecko亦會throw error 321 try{setRequestHeader("Accept-Encoding","gzip,deflate");}catch(e){} 322 // Set header so the called script knows that it's an XMLHttpRequest 323 //setRequestHeader("X-Requested-With","XMLHttpRequest"); 324 // Set the If-Modified-Since header, if ifModified mode. 325 //setRequestHeader("If-Modified-Since","Thu, 01 Jan 1970 00:00:00 GMT"); 326 if(f.method=='POST'){//&&_f.XMLHttp.setRequestHeader 327 //setRequestHeader("Content-Length",f.sendDoc.length); // use .getAttribute('method') to get 長度不一定如此 328 // 有些CGI會用Content-Type測試是XMLHttp或是regular form 329 // It may be necessary to specify "application/x-www-form-urlencoded" or "multipart/form-data" for posted XML data to be interpreted on the server. 330 setRequestHeader('Content-Type',f.fn instanceof Array&&f.fn[1]?'text/xml':'application/x-www-form-urlencoded'); // application/x-www-form-urlencoded;charset=utf-8 331 } 332 abort(); 333 open(f.method||'GET',f.URL,f.async,f.user||null,f.passwd||null); 334 //alert((f.method||'GET')+','+f.URL+','+f.async); 335 // 根據 W3C的 XMLHttpRequest 規格書上說,①在呼叫 open 時,如果readyState是4(Loaded) ②呼叫abort之後 ③發生其他錯誤,如網路問題,無窮迴圈等等,則會重設所有的值。使用全域的情況就只有第一次可以執行,因為之後的readyState是4,所以onreadystatechange 放在open之前會被清空,因此,onreadystatechange 必須放在open之後就可以避免這個問題。 http://www.javaworld.com.tw/jute/post/view?bid=49&id=170177&sty=3&age=0&tpg=1&ppg=1 336 // 每使用一次XMLHttpRequest,不管成功或失敗,都要重設onreadystatechange一次。onreadystatechange 的初始值是 null 337 // After the initial response, all event listeners will be cleared. Call open() before setting new event listeners. http://www.xulplanet.com/references/objref/XMLHttpRequest.html 338 if(f.async) 339 _f.doing=(_f.doing||0)+1, 340 onreadystatechange=typeof f.fn=='function'?f.fn:function(e){_f.HandleStateChange(e,f.URL,f.fn);},//||null 341 // 應加 clearTimeout( ) 342 setTimeout('try{getURL.'+(_f.multi_request?'q['+_f.i[f.URL]+']':'XMLHttp')+'.onreadystatechange();}catch(e){}',_f.timeout||3e5);//5*60*1000; 343 send(f.sendDoc||null); 344 if(!f.fn)return responseText;//responseXML: responseXML.loadXML(text) // 非async(異步的)能在此就得到response。Safari and Konqueror cannot understand the encoding of text files! http://www.kawa.net/works/js/jkl/parsexml.html 345 }catch(e){if(typeof f.fn=='function')f.fn(e);else if(typeof window=='object')window.status=e.message;return e;} 346 } 347 getURL.timeoutCode=-7732147; 348 349 // agent handle function 350 getURL.HandleStateChange=function(e,URL,dealFunction){ // e: object Error, dealFunction: function(return text, heads, XMLHttpRequest object, URL) | [ function, (default|NULL:responseText, others:responseXML) ] 351 var _t=0,isOKc,m=getURL.multi_request,_oXMLH; 352 if(m)m=getURL.q[isNaN(URL)?getURL.i[URL]:URL],_oXMLH=m.XMLHttp,dealFunction=m.func,URL=m.uri;else _oXMLH=getURL.XMLHttp; 353 if(dealFunction instanceof Array)_t=dealFunction[1],dealFunction=dealFunction[0]; 354 if(!dealFunction || typeof dealFunction!='function'){getURL.doing--;getURL.clean(URL);return;} 355 // http://big5.chinaz.com:88/book.chinaz.com/others/web/web/xml/index1/21.htm 356 if(!e) 357 if(typeof _oXMLH=='object'&&_oXMLH){ 358 if(_oXMLH.parseError&&_oXMLH/*.responseXML*/.parseError.errorCode!=0) 359 e=_oXMLH.parseError,e=new Error(e.errorCode,e.reason); 360 else if(_oXMLH.readyState==4){ // only if XMLHttp shows "loaded" 361 isOKc=_oXMLH.status; // condition is OK? 362 isOKc=isOKc>=200&&isOKc<300||isOKc==304||!isOKc&&(location.protocol=="file:"||location.protocol=="chrome:"); 363 if(dealFunction==getURL.HandleContent)dealFunction(0,isOKc,_oXMLH,URL);//dealFunction.apply() 364 else dealFunction( 365 isOKc?_t?_oXMLH.responseXML: 366 // JKL.ParseXML: Safari and Konqueror cannot understand the encoding of text files. 367 typeof window=='object'&&window.navigator.appVersion.indexOf("KHTML")!=-1&&!(e=escape(_oXMLH.responseText)).match("%u")&&e.match("%")?e:_oXMLH.responseText 368 :0 369 ,isOKc?_oXMLH.getAllResponseHeaders():0,_oXMLH,URL);//dealFunction.apply() 370 // URL之protocol==file: 可能需要重新.loadXML((.responseText+'').replace(/<\?xml[^?]*\?>/,"")) 371 // 用 .responseXML.documentElement 可調用 372 getURL.doing--;getURL.clean(URL); 373 return; 374 } 375 }else if(new Date-(m?m.start:getURL.startTime)>getURL.timeout) 376 // timeout & timeout function http://www.stylusstudio.com/xmldev/199912/post40380.html 377 e=new Error(getURL.timeoutCode,'Timeout!');//_oXMLH.abort(); 378 //alert(URL+'\n'+_t+'\n'+e+'\n'+_oXMLH.readyState+'\n'+dealFunction); 379 if(e){dealFunction(e,0,_oXMLH,URL);getURL.doing--;getURL.clean(URL);}//dealFunction.apply(e,URL); 380 }; 381 382 /* agent content handle function 383 有head時content包含回應,否則content表error 384 */ 385 getURL.HandleContent=function(content,head,_oXMLHttp,URL){ 386 if(head){ 387 // _oXMLHttp.getResponseHeader("Content-Length") 388 alert("URL: "+URL+"\nHead:\n"+_oXMLHttp.getAllResponseHeaders()+"\n------------------------\nLastModified: "+_oXMLHttp.getResponseHeader("Last-Modified")+"\nResult:\n"+_oXMLHttp.responseText.slice(0,200));//_oXMLHttp.responseXML.xml 389 }else{ 390 // error test時,可用getURL.XMLHttp.open("HEAD","_URL_",true);,getURL(url,dealResult,'HEAD',true)。 391 if(content instanceof Error)alert('Error occured!\n'+(typeof e=='object'&&e.number?e.number+':'+e.message:e||'')); 392 else if(typeof _oXMLHttp=='object'&&_oXMLHttp)alert((_oXMLHttp.status==404?"URL doesn't exist!":'Error occured!')+'\n\nStatus: '+_oXMLHttp.status+'\n'+_oXMLHttp.statusText); 393 } 394 }; 395 396 // 在MP模式下清乾淨queue 397 getURL.clean=function(i,force){ 398 if(force||getURL.multi_request) 399 if(!i&&isNaN(i)){ 400 if(getURL.q) 401 for(i in getURL.i) 402 try{ 403 getURL.q[getURL.i[i]].XMLHttp.abort(); 404 //getURL.q[getURL.i[i]].XMLHttp=null; 405 }catch(e){} 406 getURL.q=getURL.i=0;//null 407 }else if(!isNaN(i)||!isNaN(i=getURL.i[typeof i=='object'?i.uri:i])){ 408 try{getURL.q[i].XMLHttp.abort();}catch(e){}; 409 //getURL.q[i].XMLHttp=0; 410 delete getURL.i[getURL.q[i].uri];getURL.q[i]=0; 411 } 412 }; 413 414 // ↑XMLHttp set ================== 415 416 417 418 419 420 421 422 return ( 423 CeL.data.XML 424 ); 425 } 426 427 428 ); 429 430