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 |
---|