[2427] | 1 | /** |
---|
| 2 | * ==================================================================== |
---|
| 3 | * About |
---|
| 4 | * ==================================================================== |
---|
| 5 | * Sarissa is an ECMAScript library acting as a cross-browser wrapper for native XML APIs. |
---|
| 6 | * The library supports Gecko based browsers like Mozilla and Firefox, |
---|
| 7 | * Internet Explorer (5.5+ with MSXML3.0+), Konqueror, Safari and a little of Opera |
---|
| 8 | * @version 0.9.6.1 |
---|
| 9 | * @author: Manos Batsis, mailto: mbatsis at users full stop sourceforge full stop net |
---|
| 10 | * ==================================================================== |
---|
| 11 | * Licence |
---|
| 12 | * ==================================================================== |
---|
| 13 | * This program is free software; you can redistribute it and/or modify |
---|
| 14 | * it under the terms of the GNU General Public License version 2 or |
---|
| 15 | * the GNU Lesser General Public License version 2.1 as published by |
---|
| 16 | * the Free Software Foundation (your choice between the two). |
---|
| 17 | * |
---|
| 18 | * This program is distributed in the hope that it will be useful, |
---|
| 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
| 21 | * GNU General Public License or GNU Lesser General Public License for more details. |
---|
| 22 | * |
---|
| 23 | * You should have received a copy of the GNU General Public License |
---|
| 24 | * or GNU Lesser General Public License along with this program; if not, |
---|
| 25 | * write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
---|
| 26 | * or visit http://www.gnu.org |
---|
| 27 | * |
---|
| 28 | */ |
---|
| 29 | /** |
---|
| 30 | * <p>Sarissa is a utility class. Provides "static" methods for DOMDocument and |
---|
| 31 | * XMLHTTP objects, DOM Node serializatrion to XML strings and other goodies.</p> |
---|
| 32 | * @constructor |
---|
| 33 | */ |
---|
| 34 | function Sarissa(){}; |
---|
| 35 | /** @private */ |
---|
| 36 | Sarissa.PARSED_OK = "Document contains no parsing errors"; |
---|
| 37 | /** |
---|
| 38 | * Tells you whether transformNode and transformNodeToObject are available. This functionality |
---|
| 39 | * is contained in sarissa_ieemu_xslt.js and is deprecated. If you want to control XSLT transformations |
---|
| 40 | * use the XSLTProcessor |
---|
| 41 | * @deprecated |
---|
| 42 | * @type boolean |
---|
| 43 | */ |
---|
| 44 | Sarissa.IS_ENABLED_TRANSFORM_NODE = false; |
---|
| 45 | /** |
---|
| 46 | * tells you whether XMLHttpRequest (or equivalent) is available |
---|
| 47 | * @type boolean |
---|
| 48 | */ |
---|
| 49 | Sarissa.IS_ENABLED_XMLHTTP = false; |
---|
| 50 | /** |
---|
| 51 | * tells you whether selectNodes/selectSingleNode is available |
---|
| 52 | * @type boolean |
---|
| 53 | */ |
---|
| 54 | Sarissa.IS_ENABLED_SELECT_NODES = false; |
---|
| 55 | var _sarissa_iNsCounter = 0; |
---|
| 56 | var _SARISSA_IEPREFIX4XSLPARAM = ""; |
---|
| 57 | var _SARISSA_HAS_DOM_IMPLEMENTATION = document.implementation && true; |
---|
| 58 | var _SARISSA_HAS_DOM_CREATE_DOCUMENT = _SARISSA_HAS_DOM_IMPLEMENTATION && document.implementation.createDocument; |
---|
| 59 | var _SARISSA_HAS_DOM_FEATURE = _SARISSA_HAS_DOM_IMPLEMENTATION && document.implementation.hasFeature; |
---|
| 60 | var _SARISSA_IS_MOZ = _SARISSA_HAS_DOM_CREATE_DOCUMENT && _SARISSA_HAS_DOM_FEATURE; |
---|
| 61 | var _SARISSA_IS_SAFARI = (navigator.userAgent && navigator.vendor && (navigator.userAgent.toLowerCase().indexOf("applewebkit") != -1 || navigator.vendor.indexOf("Apple") != -1)); |
---|
| 62 | var _SARISSA_IS_IE = document.all && window.ActiveXObject && navigator.userAgent.toLowerCase().indexOf("msie") > -1 && navigator.userAgent.toLowerCase().indexOf("opera") == -1; |
---|
| 63 | if(!window.Node || !window.Node.ELEMENT_NODE){ |
---|
| 64 | var Node = {ELEMENT_NODE: 1, ATTRIBUTE_NODE: 2, TEXT_NODE: 3, CDATA_SECTION_NODE: 4, ENTITY_REFERENCE_NODE: 5, ENTITY_NODE: 6, PROCESSING_INSTRUCTION_NODE: 7, COMMENT_NODE: 8, DOCUMENT_NODE: 9, DOCUMENT_TYPE_NODE: 10, DOCUMENT_FRAGMENT_NODE: 11, NOTATION_NODE: 12}; |
---|
| 65 | }; |
---|
| 66 | |
---|
| 67 | // IE initialization |
---|
| 68 | if(_SARISSA_IS_IE){ |
---|
| 69 | // for XSLT parameter names, prefix needed by IE |
---|
| 70 | _SARISSA_IEPREFIX4XSLPARAM = "xsl:"; |
---|
| 71 | // used to store the most recent ProgID available out of the above |
---|
| 72 | var _SARISSA_DOM_PROGID = ""; |
---|
| 73 | var _SARISSA_XMLHTTP_PROGID = ""; |
---|
| 74 | /** |
---|
| 75 | * Called when the Sarissa_xx.js file is parsed, to pick most recent |
---|
| 76 | * ProgIDs for IE, then gets destroyed. |
---|
| 77 | * @param idList an array of MSXML PROGIDs from which the most recent will be picked for a given object |
---|
| 78 | * @param enabledList an array of arrays where each array has two items; the index of the PROGID for which a certain feature is enabled |
---|
| 79 | */ |
---|
| 80 | pickRecentProgID = function (idList, enabledList){ |
---|
| 81 | // found progID flag |
---|
| 82 | var bFound = false; |
---|
| 83 | for(var i=0; i < idList.length && !bFound; i++){ |
---|
| 84 | try{ |
---|
| 85 | var oDoc = new ActiveXObject(idList[i]); |
---|
| 86 | o2Store = idList[i]; |
---|
| 87 | bFound = true; |
---|
| 88 | for(var j=0;j<enabledList.length;j++) |
---|
| 89 | if(i <= enabledList[j][1]) |
---|
| 90 | Sarissa["IS_ENABLED_"+enabledList[j][0]] = true; |
---|
| 91 | }catch (objException){ |
---|
| 92 | // trap; try next progID |
---|
| 93 | }; |
---|
| 94 | }; |
---|
| 95 | if (!bFound) |
---|
| 96 | throw "Could not retreive a valid progID of Class: " + idList[idList.length-1]+". (original exception: "+e+")"; |
---|
| 97 | idList = null; |
---|
| 98 | return o2Store; |
---|
| 99 | }; |
---|
| 100 | // pick best available MSXML progIDs |
---|
| 101 | _SARISSA_DOM_PROGID = pickRecentProgID(["Msxml2.DOMDocument.5.0", "Msxml2.DOMDocument.4.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"], [["SELECT_NODES", 2],["TRANSFORM_NODE", 2]]); |
---|
| 102 | _SARISSA_XMLHTTP_PROGID = pickRecentProgID(["Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"], [["XMLHTTP", 4]]); |
---|
| 103 | _SARISSA_THREADEDDOM_PROGID = pickRecentProgID(["Msxml2.FreeThreadedDOMDocument.5.0", "MSXML2.FreeThreadedDOMDocument.4.0", "MSXML2.FreeThreadedDOMDocument.3.0"]); |
---|
| 104 | _SARISSA_XSLTEMPLATE_PROGID = pickRecentProgID(["Msxml2.XSLTemplate.5.0", "Msxml2.XSLTemplate.4.0", "MSXML2.XSLTemplate.3.0"], [["XSLTPROC", 2]]); |
---|
| 105 | // we dont need this anymore |
---|
| 106 | pickRecentProgID = null; |
---|
| 107 | //============================================ |
---|
| 108 | // Factory methods (IE) |
---|
| 109 | //============================================ |
---|
| 110 | // see non-IE version |
---|
| 111 | Sarissa.getDomDocument = function(sUri, sName){ |
---|
| 112 | var oDoc = new ActiveXObject(_SARISSA_DOM_PROGID); |
---|
| 113 | // if a root tag name was provided, we need to load it in the DOM |
---|
| 114 | // object |
---|
| 115 | if (sName){ |
---|
| 116 | // if needed, create an artifical namespace prefix the way Moz |
---|
| 117 | // does |
---|
| 118 | if (sUri){ |
---|
| 119 | oDoc.loadXML("<a" + _sarissa_iNsCounter + ":" + sName + " xmlns:a" + _sarissa_iNsCounter + "=\"" + sUri + "\" />"); |
---|
| 120 | // don't use the same prefix again |
---|
| 121 | ++_sarissa_iNsCounter; |
---|
| 122 | } |
---|
| 123 | else |
---|
| 124 | oDoc.loadXML("<" + sName + "/>"); |
---|
| 125 | }; |
---|
| 126 | return oDoc; |
---|
| 127 | }; |
---|
| 128 | // see non-IE version |
---|
| 129 | Sarissa.getParseErrorText = function (oDoc) { |
---|
| 130 | var parseErrorText = Sarissa.PARSED_OK; |
---|
| 131 | if(oDoc.parseError != 0){ |
---|
| 132 | parseErrorText = "XML Parsing Error: " + oDoc.parseError.reason + |
---|
| 133 | "\nLocation: " + oDoc.parseError.url + |
---|
| 134 | "\nLine Number " + oDoc.parseError.line + ", Column " + |
---|
| 135 | oDoc.parseError.linepos + |
---|
| 136 | ":\n" + oDoc.parseError.srcText + |
---|
| 137 | "\n"; |
---|
| 138 | for(var i = 0; i < oDoc.parseError.linepos;i++){ |
---|
| 139 | parseErrorText += "-"; |
---|
| 140 | }; |
---|
| 141 | parseErrorText += "^\n"; |
---|
| 142 | }; |
---|
| 143 | return parseErrorText; |
---|
| 144 | }; |
---|
| 145 | // see non-IE version |
---|
| 146 | Sarissa.setXpathNamespaces = function(oDoc, sNsSet) { |
---|
| 147 | oDoc.setProperty("SelectionLanguage", "XPath"); |
---|
| 148 | oDoc.setProperty("SelectionNamespaces", sNsSet); |
---|
| 149 | }; |
---|
| 150 | /** |
---|
| 151 | * Basic implementation of Mozilla's XSLTProcessor for IE. |
---|
| 152 | * Reuses the same XSLT stylesheet for multiple transforms |
---|
| 153 | * @constructor |
---|
| 154 | */ |
---|
| 155 | XSLTProcessor = function(){ |
---|
| 156 | this.template = new ActiveXObject(_SARISSA_XSLTEMPLATE_PROGID); |
---|
| 157 | this.processor = null; |
---|
| 158 | }; |
---|
| 159 | /** |
---|
| 160 | * Impoprts the given XSLT DOM and compiles it to a reusable transform |
---|
| 161 | * @argument xslDoc The XSLT DOMDocument to import |
---|
| 162 | */ |
---|
| 163 | XSLTProcessor.prototype.importStylesheet = function(xslDoc){ |
---|
| 164 | // convert stylesheet to free threaded |
---|
| 165 | var converted = new ActiveXObject(_SARISSA_THREADEDDOM_PROGID); |
---|
| 166 | converted.loadXML(xslDoc.xml); |
---|
| 167 | this.template.stylesheet = converted; |
---|
| 168 | this.processor = this.template.createProcessor(); |
---|
| 169 | // (re)set default param values |
---|
| 170 | this.paramsSet = new Array(); |
---|
| 171 | }; |
---|
| 172 | /** |
---|
| 173 | * Transform the given XML DOM |
---|
| 174 | * @argument sourceDoc The XML DOMDocument to transform |
---|
| 175 | * @return The transformation result as a DOM Document |
---|
| 176 | */ |
---|
| 177 | XSLTProcessor.prototype.transformToDocument = function(sourceDoc){ |
---|
| 178 | this.processor.input = sourceDoc; |
---|
| 179 | var outDoc = new ActiveXObject(_SARISSA_DOM_PROGID); |
---|
| 180 | this.processor.output = outDoc; |
---|
| 181 | this.processor.transform(); |
---|
| 182 | return outDoc; |
---|
| 183 | }; |
---|
| 184 | /** |
---|
| 185 | * Set global XSLT parameter of the imported stylesheet |
---|
| 186 | * @argument nsURI The parameter namespace URI |
---|
| 187 | * @argument name The parameter base name |
---|
| 188 | * @argument value The new parameter value |
---|
| 189 | */ |
---|
| 190 | XSLTProcessor.prototype.setParameter = function(nsURI, name, value){ |
---|
| 191 | /* nsURI is optional but cannot be null */ |
---|
| 192 | if(nsURI){ |
---|
| 193 | this.processor.addParameter(name, value, nsURI); |
---|
| 194 | }else{ |
---|
| 195 | this.processor.addParameter(name, value); |
---|
| 196 | }; |
---|
| 197 | /* update updated params for getParameter */ |
---|
| 198 | if(!this.paramsSet[""+nsURI]){ |
---|
| 199 | this.paramsSet[""+nsURI] = new Array(); |
---|
| 200 | }; |
---|
| 201 | this.paramsSet[""+nsURI][name] = value; |
---|
| 202 | }; |
---|
| 203 | /** |
---|
| 204 | * Gets a parameter if previously set by setParameter. Returns null |
---|
| 205 | * otherwise |
---|
| 206 | * @argument name The parameter base name |
---|
| 207 | * @argument value The new parameter value |
---|
| 208 | * @return The parameter value if reviously set by setParameter, null otherwise |
---|
| 209 | */ |
---|
| 210 | XSLTProcessor.prototype.getParameter = function(nsURI, name){ |
---|
| 211 | nsURI = nsURI || ""; |
---|
| 212 | if(nsURI in this.paramsSet && name in this.paramsSet[nsURI]){ |
---|
| 213 | return this.paramsSet[nsURI][name]; |
---|
| 214 | }else{ |
---|
| 215 | return null; |
---|
| 216 | }; |
---|
| 217 | }; |
---|
| 218 | } |
---|
| 219 | else{ /* end IE initialization, try to deal with real browsers now ;-) */ |
---|
| 220 | if(_SARISSA_HAS_DOM_CREATE_DOCUMENT){ |
---|
| 221 | /** |
---|
| 222 | * <p>Ensures the document was loaded correctly, otherwise sets the |
---|
| 223 | * parseError to -1 to indicate something went wrong. Internal use</p> |
---|
| 224 | * @private |
---|
| 225 | */ |
---|
| 226 | Sarissa.__handleLoad__ = function(oDoc){ |
---|
| 227 | if (!oDoc.documentElement || oDoc.documentElement.tagName == "parsererror") |
---|
| 228 | oDoc.parseError = -1; |
---|
| 229 | Sarissa.__setReadyState__(oDoc, 4); |
---|
| 230 | }; |
---|
| 231 | /** |
---|
| 232 | * <p>Attached by an event handler to the load event. Internal use.</p> |
---|
| 233 | * @private |
---|
| 234 | */ |
---|
| 235 | _sarissa_XMLDocument_onload = function(){ |
---|
| 236 | Sarissa.__handleLoad__(this); |
---|
| 237 | }; |
---|
| 238 | /** |
---|
| 239 | * <p>Sets the readyState property of the given DOM Document object. |
---|
| 240 | * Internal use.</p> |
---|
| 241 | * @private |
---|
| 242 | * @argument oDoc the DOM Document object to fire the |
---|
| 243 | * readystatechange event |
---|
| 244 | * @argument iReadyState the number to change the readystate property to |
---|
| 245 | */ |
---|
| 246 | Sarissa.__setReadyState__ = function(oDoc, iReadyState){ |
---|
| 247 | oDoc.readyState = iReadyState; |
---|
| 248 | if (oDoc.onreadystatechange != null && typeof oDoc.onreadystatechange == "function") |
---|
| 249 | oDoc.onreadystatechange(); |
---|
| 250 | }; |
---|
| 251 | Sarissa.getDomDocument = function(sUri, sName){ |
---|
| 252 | var oDoc = document.implementation.createDocument(sUri?sUri:"", sName?sName:"", null); |
---|
| 253 | oDoc.addEventListener("load", _sarissa_XMLDocument_onload, false); |
---|
| 254 | return oDoc; |
---|
| 255 | }; |
---|
| 256 | if(window.XMLDocument){ |
---|
| 257 | /** |
---|
| 258 | * <p>Emulate IE's onreadystatechange attribute</p> |
---|
| 259 | */ |
---|
| 260 | XMLDocument.prototype.onreadystatechange = null; |
---|
| 261 | /** |
---|
| 262 | * <p>Emulates IE's readyState property, which always gives an integer from 0 to 4:</p> |
---|
| 263 | * <ul><li>1 == LOADING,</li> |
---|
| 264 | * <li>2 == LOADED,</li> |
---|
| 265 | * <li>3 == INTERACTIVE,</li> |
---|
| 266 | * <li>4 == COMPLETED</li></ul> |
---|
| 267 | */ |
---|
| 268 | XMLDocument.prototype.readyState = 0; |
---|
| 269 | /** |
---|
| 270 | * <p>Emulate IE's parseError attribute</p> |
---|
| 271 | */ |
---|
| 272 | XMLDocument.prototype.parseError = 0; |
---|
| 273 | |
---|
| 274 | // NOTE: setting async to false will only work with documents |
---|
| 275 | // called over HTTP (meaning a server), not the local file system, |
---|
| 276 | // unless you are using Moz 1.4+. |
---|
| 277 | // BTW the try>catch block is for 1.4; I haven't found a way to check if |
---|
| 278 | // the property is implemented without |
---|
| 279 | // causing an error and I dont want to use user agent stuff for that... |
---|
| 280 | var _SARISSA_SYNC_NON_IMPLEMENTED = false;// ("async" in XMLDocument.prototype) ? false: true; |
---|
| 281 | /** |
---|
| 282 | * <p>Keeps a handle to the original load() method. Internal use and only |
---|
| 283 | * if Mozilla version is lower than 1.4</p> |
---|
| 284 | * @private |
---|
| 285 | */ |
---|
| 286 | XMLDocument.prototype._sarissa_load = XMLDocument.prototype.load; |
---|
| 287 | |
---|
| 288 | /** |
---|
| 289 | * <p>Overrides the original load method to provide synchronous loading for |
---|
| 290 | * Mozilla versions prior to 1.4, using an XMLHttpRequest object (if |
---|
| 291 | * async is set to false)</p> |
---|
| 292 | * @returns the DOM Object as it was before the load() call (may be empty) |
---|
| 293 | */ |
---|
| 294 | XMLDocument.prototype.load = function(sURI) { |
---|
| 295 | var oDoc = document.implementation.createDocument("", "", null); |
---|
| 296 | Sarissa.copyChildNodes(this, oDoc); |
---|
| 297 | this.parseError = 0; |
---|
| 298 | Sarissa.__setReadyState__(this, 1); |
---|
| 299 | try { |
---|
| 300 | if(this.async == false && _SARISSA_SYNC_NON_IMPLEMENTED) { |
---|
| 301 | var tmp = new XMLHttpRequest(); |
---|
| 302 | tmp.open("GET", sURI, false); |
---|
| 303 | tmp.send(null); |
---|
| 304 | Sarissa.__setReadyState__(this, 2); |
---|
| 305 | Sarissa.copyChildNodes(tmp.responseXML, this); |
---|
| 306 | Sarissa.__setReadyState__(this, 3); |
---|
| 307 | } |
---|
| 308 | else { |
---|
| 309 | this._sarissa_load(sURI); |
---|
| 310 | }; |
---|
| 311 | } |
---|
| 312 | catch (objException) { |
---|
| 313 | this.parseError = -1; |
---|
| 314 | } |
---|
| 315 | finally { |
---|
| 316 | if(this.async == false){ |
---|
| 317 | Sarissa.__handleLoad__(this); |
---|
| 318 | }; |
---|
| 319 | }; |
---|
| 320 | return oDoc; |
---|
| 321 | }; |
---|
| 322 | |
---|
| 323 | |
---|
| 324 | }//if(window.XMLDocument) |
---|
| 325 | else if(document.implementation && document.implementation.hasFeature && document.implementation.hasFeature('LS', '3.0')){ |
---|
| 326 | Document.prototype.async = true; |
---|
| 327 | Document.prototype.onreadystatechange = null; |
---|
| 328 | Document.prototype.parseError = 0; |
---|
| 329 | Document.prototype.load = function(sURI) { |
---|
| 330 | var parser = document.implementation.createLSParser(this.async ? document.implementation.MODE_ASYNCHRONOUS : document.implementation.MODE_SYNCHRONOUS, null); |
---|
| 331 | if(this.async){ |
---|
| 332 | var self = this; |
---|
| 333 | parser.addEventListener("load", |
---|
| 334 | function(e) { |
---|
| 335 | self.readyState = 4; |
---|
| 336 | Sarissa.copyChildNodes(e.newDocument, self.documentElement, false); |
---|
| 337 | self.onreadystatechange.call(); |
---|
| 338 | }, |
---|
| 339 | false); |
---|
| 340 | }; |
---|
| 341 | try { |
---|
| 342 | var oDoc = parser.parseURI(sURI); |
---|
| 343 | } |
---|
| 344 | catch(e){ |
---|
| 345 | this.parseError = -1; |
---|
| 346 | }; |
---|
| 347 | if(!this.async) |
---|
| 348 | Sarissa.copyChildNodes(oDoc, this.documentElement, false); |
---|
| 349 | return oDoc; |
---|
| 350 | }; |
---|
| 351 | /** |
---|
| 352 | * <p>Factory method to obtain a new DOM Document object</p> |
---|
| 353 | * @argument sUri the namespace of the root node (if any) |
---|
| 354 | * @argument sUri the local name of the root node (if any) |
---|
| 355 | * @returns a new DOM Document |
---|
| 356 | */ |
---|
| 357 | Sarissa.getDomDocument = function(sUri, sName){ |
---|
| 358 | return document.implementation.createDocument(sUri?sUri:"", sName?sName:"", null); |
---|
| 359 | }; |
---|
| 360 | }; |
---|
| 361 | };//if(_SARISSA_HAS_DOM_CREATE_DOCUMENT) |
---|
| 362 | }; |
---|
| 363 | //========================================== |
---|
| 364 | // Common stuff |
---|
| 365 | //========================================== |
---|
| 366 | if(!window.DOMParser){ |
---|
| 367 | /* |
---|
| 368 | * DOMParser is a utility class, used to construct DOMDocuments from XML strings |
---|
| 369 | * @constructor |
---|
| 370 | */ |
---|
| 371 | DOMParser = function() { |
---|
| 372 | }; |
---|
| 373 | if(_SARISSA_IS_SAFARI){ |
---|
| 374 | /** |
---|
| 375 | * Construct a new DOM Document from the given XMLstring |
---|
| 376 | * @param sXml the given XML string |
---|
| 377 | * @param contentType the content type of the document the given string represents (one of text/xml, application/xml, application/xhtml+xml). |
---|
| 378 | * @return a new DOM Document from the given XML string |
---|
| 379 | */ |
---|
| 380 | DOMParser.prototype.parseFromString = function(sXml, contentType){ |
---|
| 381 | if(contentType.toLowerCase() != "application/xml"){ |
---|
| 382 | throw "Cannot handle content type: \"" + contentType + "\""; |
---|
| 383 | }; |
---|
| 384 | var xmlhttp = new XMLHttpRequest(); |
---|
| 385 | xmlhttp.open("GET", "data:text/xml;charset=utf-8," + encodeURIComponent(str), false); |
---|
| 386 | xmlhttp.send(null); |
---|
| 387 | return xmlhttp.responseXML; |
---|
| 388 | }; |
---|
| 389 | }else if(Sarissa.getDomDocument && Sarissa.getDomDocument() && "loadXML" in Sarissa.getDomDocument()){ |
---|
| 390 | DOMParser.prototype.parseFromString = function(sXml, contentType){ |
---|
| 391 | var doc = Sarissa.getDomDocument(); |
---|
| 392 | doc.loadXML(sXml); |
---|
| 393 | return doc; |
---|
| 394 | }; |
---|
| 395 | }; |
---|
| 396 | }; |
---|
| 397 | |
---|
| 398 | if(window.XMLHttpRequest){ |
---|
| 399 | Sarissa.IS_ENABLED_XMLHTTP = true; |
---|
| 400 | } |
---|
| 401 | else if(_SARISSA_IS_IE){ |
---|
| 402 | /** |
---|
| 403 | * Emulate XMLHttpRequest |
---|
| 404 | * @constructor |
---|
| 405 | */ |
---|
| 406 | XMLHttpRequest = function() { |
---|
| 407 | return new ActiveXObject(_SARISSA_XMLHTTP_PROGID); |
---|
| 408 | }; |
---|
| 409 | Sarissa.IS_ENABLED_XMLHTTP = true; |
---|
| 410 | }; |
---|
| 411 | |
---|
| 412 | if(!window.document.importNode && _SARISSA_IS_IE){ |
---|
| 413 | try{ |
---|
| 414 | /** |
---|
| 415 | * Implements importNode for the current window document in IE using innerHTML. |
---|
| 416 | * Testing showed that DOM was multiple times slower than innerHTML for this, |
---|
| 417 | * sorry folks. If you encounter trouble (who knows what IE does behind innerHTML) |
---|
| 418 | * please gimme a call. |
---|
| 419 | * @param oNode the Node to import |
---|
| 420 | * @param bChildren whether to include the children of oNode |
---|
| 421 | * @returns the imported node for further use |
---|
| 422 | */ |
---|
| 423 | window.document.importNode = function(oNode, bChildren){ |
---|
| 424 | var importNode = document.createElement("div"); |
---|
| 425 | if(bChildren) |
---|
| 426 | importNode.innerHTML = Sarissa.serialize(oNode); |
---|
| 427 | else |
---|
| 428 | importNode.innerHTML = Sarissa.serialize(oNode.cloneNode(false)); |
---|
| 429 | return importNode.firstChild; |
---|
| 430 | }; |
---|
| 431 | }catch(e){}; |
---|
| 432 | }; |
---|
| 433 | if(!Sarissa.getParseErrorText){ |
---|
| 434 | /** |
---|
| 435 | * <p>Returns a human readable description of the parsing error. Usefull |
---|
| 436 | * for debugging. Tip: append the returned error string in a <pre> |
---|
| 437 | * element if you want to render it.</p> |
---|
| 438 | * <p>Many thanks to Christian Stocker for the initial patch.</p> |
---|
| 439 | * @argument oDoc The target DOM document |
---|
| 440 | * @returns The parsing error description of the target Document in |
---|
| 441 | * human readable form (preformated text) |
---|
| 442 | */ |
---|
| 443 | Sarissa.getParseErrorText = function (oDoc){ |
---|
| 444 | var parseErrorText = Sarissa.PARSED_OK; |
---|
| 445 | if(oDoc && oDoc.parseError && oDoc.parseError != 0){ |
---|
| 446 | /*moz*/ |
---|
| 447 | if(oDoc.documentElement.tagName == "parsererror"){ |
---|
| 448 | parseErrorText = oDoc.documentElement.firstChild.data; |
---|
| 449 | parseErrorText += "\n" + oDoc.documentElement.firstChild.nextSibling.firstChild.data; |
---|
| 450 | }/*konq*/ |
---|
| 451 | else{ |
---|
| 452 | parseErrorText = Sarissa.getText(oDoc.documentElement);/*.getElementsByTagName("h1")[0], false) + "\n"; |
---|
| 453 | parseErrorText += Sarissa.getText(oDoc.documentElement.getElementsByTagName("body")[0], false) + "\n"; |
---|
| 454 | parseErrorText += Sarissa.getText(oDoc.documentElement.getElementsByTagName("pre")[0], false);*/ |
---|
| 455 | }; |
---|
| 456 | }; |
---|
| 457 | return parseErrorText; |
---|
| 458 | }; |
---|
| 459 | }; |
---|
| 460 | Sarissa.getText = function(oNode, deep){ |
---|
| 461 | var s = ""; |
---|
| 462 | var nodes = oNode.childNodes; |
---|
| 463 | for(var i=0; i < nodes.length; i++){ |
---|
| 464 | var node = nodes[i]; |
---|
| 465 | var nodeType = node.nodeType; |
---|
| 466 | if(nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE){ |
---|
| 467 | s += node.data; |
---|
| 468 | }else if(deep == true |
---|
| 469 | && (nodeType == Node.ELEMENT_NODE |
---|
| 470 | || nodeType == Node.DOCUMENT_NODE |
---|
| 471 | || nodeType == Node.DOCUMENT_FRAGMENT_NODE)){ |
---|
| 472 | s += Sarissa.getText(node, true); |
---|
| 473 | }; |
---|
| 474 | }; |
---|
| 475 | return s; |
---|
| 476 | }; |
---|
| 477 | if(window.XMLSerializer){ |
---|
| 478 | /** |
---|
| 479 | * <p>Factory method to obtain the serialization of a DOM Node</p> |
---|
| 480 | * @returns the serialized Node as an XML string |
---|
| 481 | */ |
---|
| 482 | Sarissa.serialize = function(oDoc){ |
---|
| 483 | var s = null; |
---|
| 484 | if(oDoc){ |
---|
| 485 | s = oDoc.innerHTML?oDoc.innerHTML:(new XMLSerializer()).serializeToString(oDoc); |
---|
| 486 | }; |
---|
| 487 | return s; |
---|
| 488 | }; |
---|
| 489 | }else{ |
---|
| 490 | if(Sarissa.getDomDocument && (Sarissa.getDomDocument("","foo", null)).xml){ |
---|
| 491 | // see non-IE version |
---|
| 492 | Sarissa.serialize = function(oDoc) { |
---|
| 493 | var s = null; |
---|
| 494 | if(oDoc){ |
---|
| 495 | s = oDoc.innerHTML?oDoc.innerHTML:oDoc.xml; |
---|
| 496 | }; |
---|
| 497 | return s; |
---|
| 498 | }; |
---|
| 499 | /** |
---|
| 500 | * Utility class to serialize DOM Node objects to XML strings |
---|
| 501 | * @constructor |
---|
| 502 | */ |
---|
| 503 | XMLSerializer = function(){}; |
---|
| 504 | /** |
---|
| 505 | * Serialize the given DOM Node to an XML string |
---|
| 506 | * @param oNode the DOM Node to serialize |
---|
| 507 | */ |
---|
| 508 | XMLSerializer.prototype.serializeToString = function(oNode) { |
---|
| 509 | return oNode.xml; |
---|
| 510 | }; |
---|
| 511 | }; |
---|
| 512 | }; |
---|
| 513 | |
---|
| 514 | /** |
---|
| 515 | * strips tags from a markup string |
---|
| 516 | */ |
---|
| 517 | Sarissa.stripTags = function (s) { |
---|
| 518 | return s.replace(/<[^>]+>/g,""); |
---|
| 519 | }; |
---|
| 520 | /** |
---|
| 521 | * <p>Deletes all child nodes of the given node</p> |
---|
| 522 | * @argument oNode the Node to empty |
---|
| 523 | */ |
---|
| 524 | Sarissa.clearChildNodes = function(oNode) { |
---|
| 525 | // need to check for firstChild due to opera 8 bug with hasChildNodes |
---|
| 526 | while(oNode.firstChild){ |
---|
| 527 | oNode.removeChild(oNode.firstChild); |
---|
| 528 | }; |
---|
| 529 | }; |
---|
| 530 | /** |
---|
| 531 | * <p> Copies the childNodes of nodeFrom to nodeTo</p> |
---|
| 532 | * <p> <b>Note:</b> The second object's original content is deleted before |
---|
| 533 | * the copy operation, unless you supply a true third parameter</p> |
---|
| 534 | * @argument nodeFrom the Node to copy the childNodes from |
---|
| 535 | * @argument nodeTo the Node to copy the childNodes to |
---|
| 536 | * @argument bPreserveExisting whether to preserve the original content of nodeTo, default is false |
---|
| 537 | */ |
---|
| 538 | Sarissa.copyChildNodes = function(nodeFrom, nodeTo, bPreserveExisting) { |
---|
| 539 | if((!nodeFrom) || (!nodeTo)){ |
---|
| 540 | throw "Both source and destination nodes must be provided"; |
---|
| 541 | }; |
---|
| 542 | if(!bPreserveExisting){ |
---|
| 543 | Sarissa.clearChildNodes(nodeTo); |
---|
| 544 | }; |
---|
| 545 | var ownerDoc = nodeTo.nodeType == Node.DOCUMENT_NODE ? nodeTo : nodeTo.ownerDocument; |
---|
| 546 | var nodes = nodeFrom.childNodes; |
---|
| 547 | if(ownerDoc.importNode && (!_SARISSA_IS_IE)) { |
---|
| 548 | for(var i=0;i < nodes.length;i++) { |
---|
| 549 | nodeTo.appendChild(ownerDoc.importNode(nodes[i], true)); |
---|
| 550 | }; |
---|
| 551 | } |
---|
| 552 | else{ |
---|
| 553 | for(var i=0;i < nodes.length;i++) { |
---|
| 554 | nodeTo.appendChild(nodes[i].cloneNode(true)); |
---|
| 555 | }; |
---|
| 556 | }; |
---|
| 557 | }; |
---|
| 558 | |
---|
| 559 | /** |
---|
| 560 | * <p> Moves the childNodes of nodeFrom to nodeTo</p> |
---|
| 561 | * <p> <b>Note:</b> The second object's original content is deleted before |
---|
| 562 | * the move operation, unless you supply a true third parameter</p> |
---|
| 563 | * @argument nodeFrom the Node to copy the childNodes from |
---|
| 564 | * @argument nodeTo the Node to copy the childNodes to |
---|
| 565 | * @argument bPreserveExisting whether to preserve the original content of nodeTo, default is |
---|
| 566 | */ |
---|
| 567 | Sarissa.moveChildNodes = function(nodeFrom, nodeTo, bPreserveExisting) { |
---|
| 568 | if((!nodeFrom) || (!nodeTo)){ |
---|
| 569 | throw "Both source and destination nodes must be provided"; |
---|
| 570 | }; |
---|
| 571 | if(!bPreserveExisting){ |
---|
| 572 | Sarissa.clearChildNodes(nodeTo); |
---|
| 573 | }; |
---|
| 574 | var nodes = nodeFrom.childNodes; |
---|
| 575 | // if within the same doc, just move, else copy and delete |
---|
| 576 | if(nodeFrom.ownerDocument == nodeTo.ownerDocument){ |
---|
| 577 | while(nodeFrom.firstChild){ |
---|
| 578 | nodeTo.appendChild(nodeFrom.firstChild); |
---|
| 579 | }; |
---|
| 580 | }else{ |
---|
| 581 | var ownerDoc = nodeTo.nodeType == Node.DOCUMENT_NODE ? nodeTo : nodeTo.ownerDocument; |
---|
| 582 | if(ownerDoc.importNode && (!_SARISSA_IS_IE)) { |
---|
| 583 | for(var i=0;i < nodes.length;i++) { |
---|
| 584 | nodeTo.appendChild(ownerDoc.importNode(nodes[i], true)); |
---|
| 585 | }; |
---|
| 586 | }else{ |
---|
| 587 | for(var i=0;i < nodes.length;i++) { |
---|
| 588 | nodeTo.appendChild(nodes[i].cloneNode(true)); |
---|
| 589 | }; |
---|
| 590 | }; |
---|
| 591 | Sarissa.clearChildNodes(nodeFrom); |
---|
| 592 | }; |
---|
| 593 | }; |
---|
| 594 | |
---|
| 595 | /** |
---|
| 596 | * <p>Serialize any object to an XML string. All properties are serialized using the property name |
---|
| 597 | * as the XML element name. Array elements are rendered as <code>array-item</code> elements, |
---|
| 598 | * using their index/key as the value of the <code>key</code> attribute.</p> |
---|
| 599 | * @argument anyObject the object to serialize |
---|
| 600 | * @argument objectName a name for that object |
---|
| 601 | * @return the XML serializationj of the given object as a string |
---|
| 602 | */ |
---|
| 603 | Sarissa.xmlize = function(anyObject, objectName, indentSpace){ |
---|
| 604 | indentSpace = indentSpace?indentSpace:''; |
---|
| 605 | var s = indentSpace + '<' + objectName + '>'; |
---|
| 606 | var isLeaf = false; |
---|
| 607 | if(!(anyObject instanceof Object) || anyObject instanceof Number || anyObject instanceof String |
---|
| 608 | || anyObject instanceof Boolean || anyObject instanceof Date){ |
---|
| 609 | s += Sarissa.escape(""+anyObject); |
---|
| 610 | isLeaf = true; |
---|
| 611 | }else{ |
---|
| 612 | s += "\n"; |
---|
| 613 | var itemKey = ''; |
---|
| 614 | var isArrayItem = anyObject instanceof Array; |
---|
| 615 | for(var name in anyObject){ |
---|
| 616 | s += Sarissa.xmlize(anyObject[name], (isArrayItem?"array-item key=\""+name+"\"":name), indentSpace + " "); |
---|
| 617 | }; |
---|
| 618 | s += indentSpace; |
---|
| 619 | }; |
---|
| 620 | return s += (objectName.indexOf(' ')!=-1?"</array-item>\n":"</" + objectName + ">\n"); |
---|
| 621 | }; |
---|
| 622 | |
---|
| 623 | /** |
---|
| 624 | * Escape the given string chacters that correspond to the five predefined XML entities |
---|
| 625 | * @param sXml the string to escape |
---|
| 626 | */ |
---|
| 627 | Sarissa.escape = function(sXml){ |
---|
| 628 | return sXml.replace(/&/g, "&") |
---|
| 629 | .replace(/</g, "<") |
---|
| 630 | .replace(/>/g, ">") |
---|
| 631 | .replace(/"/g, """) |
---|
| 632 | .replace(/'/g, "'"); |
---|
| 633 | }; |
---|
| 634 | |
---|
| 635 | /** |
---|
| 636 | * Unescape the given string. This turns the occurences of the predefined XML |
---|
| 637 | * entities to become the characters they represent correspond to the five predefined XML entities |
---|
| 638 | * @param sXml the string to unescape |
---|
| 639 | */ |
---|
| 640 | Sarissa.unescape = function(sXml){ |
---|
| 641 | return sXml.replace(/'/g,"'") |
---|
| 642 | .replace(/"/g,"\"") |
---|
| 643 | .replace(/>/g,">") |
---|
| 644 | .replace(/</g,"<") |
---|
| 645 | .replace(/&/g,"&"); |
---|
| 646 | }; |
---|
| 647 | // EOF |
---|