4 * ====================================================================
6 * ====================================================================
7 * Sarissa is an ECMAScript library acting as a cross-browser wrapper for native XML APIs.
8 * The library supports Gecko based browsers like Mozilla and Firefox,
9 * Internet Explorer (5.5+ with MSXML3.0+), Konqueror, Safari and a little of Opera
10 * @version @sarissa.version@
11 * @author: Manos Batsis, mailto: mbatsis at users full stop sourceforge full stop net
12 * ====================================================================
14 * ====================================================================
15 * Sarissa is free software distributed under the GNU GPL version 2 (see <a href="gpl.txt">gpl.txt</a>) or higher,
16 * GNU LGPL version 2.1 (see <a href="lgpl.txt">lgpl.txt</a>) or higher and Apache Software License 2.0 or higher
17 * (see <a href="asl.txt">asl.txt</a>). This means you can choose one of the three and use that if you like. If
18 * you make modifications under the ASL, i would appreciate it if you submitted those.
19 * In case your copy of Sarissa does not include the license texts, you may find
20 * them online in various formats at <a href="http://www.gnu.org">http://www.gnu.org</a> and
21 * <a href="http://www.apache.org">http://www.apache.org</a>.
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
23 * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
24 * WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE
25 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
26 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
28 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 * <p>Sarissa is a utility class. Provides "static" methods for DOMDocument,
33 * DOM Node serialization to XML strings and other utility goodies.</p>
37 Sarissa
.PARSED_OK
= "Document contains no parsing errors";
38 Sarissa
.PARSED_EMPTY
= "Document is empty";
39 Sarissa
.PARSED_UNKNOWN_ERROR
= "Not well-formed or other error";
40 var _sarissa_iNsCounter
= 0;
41 var _SARISSA_IEPREFIX4XSLPARAM
= "";
42 var _SARISSA_HAS_DOM_IMPLEMENTATION
= document
.implementation
&& true;
43 var _SARISSA_HAS_DOM_CREATE_DOCUMENT
= _SARISSA_HAS_DOM_IMPLEMENTATION
&& document
.implementation
.createDocument
;
44 var _SARISSA_HAS_DOM_FEATURE
= _SARISSA_HAS_DOM_IMPLEMENTATION
&& document
.implementation
.hasFeature
;
45 var _SARISSA_IS_MOZ
= _SARISSA_HAS_DOM_CREATE_DOCUMENT
&& _SARISSA_HAS_DOM_FEATURE
;
46 var _SARISSA_IS_SAFARI
= (navigator
.userAgent
&& navigator
.vendor
&& (navigator
.userAgent
.toLowerCase().indexOf("applewebkit") != -1 || navigator
.vendor
.indexOf("Apple") != -1));
47 var _SARISSA_IS_IE
= document
.all
&& window
.ActiveXObject
&& navigator
.userAgent
.toLowerCase().indexOf("msie") > -1 && navigator
.userAgent
.toLowerCase().indexOf("opera") == -1;
48 if(!window
.Node
|| !Node
.ELEMENT_NODE
){
49 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};
52 if( typeof XMLDocument
== "undefined" && typeof Document
!= "undefined"){ XMLDocument
= Document
; }
56 // for XSLT parameter names, prefix needed by IE
57 _SARISSA_IEPREFIX4XSLPARAM
= "xsl:";
58 // used to store the most recent ProgID available out of the above
59 var _SARISSA_DOM_PROGID
= "";
60 var _SARISSA_XMLHTTP_PROGID
= "";
61 var _SARISSA_DOM_XMLWRITER
= "";
63 * Called when the Sarissa_xx.js file is parsed, to pick most recent
64 * ProgIDs for IE, then gets destroyed.
66 * @param idList an array of MSXML PROGIDs from which the most recent will be picked for a given object
67 * @param enabledList an array of arrays where each array has two items; the index of the PROGID for which a certain feature is enabled
69 Sarissa
.pickRecentProgID = function (idList
){
71 var bFound
= false, e
;
72 for(var i
=0; i
< idList
.length
&& !bFound
; i
++){
74 var _
= new ActiveXObject(idList
[i
]);
76 var o2Store
= idList
[i
];
78 }catch (objException
){
79 // trap; try next progID
84 throw "Could not retrieve a valid progID of Class: " + idList
[idList
.length
-1]+". (original exception: "+e
+")";
89 // pick best available MSXML progIDs
90 _SARISSA_DOM_PROGID
= null;
91 _SARISSA_THREADEDDOM_PROGID
= null;
92 _SARISSA_XSLTEMPLATE_PROGID
= null;
93 _SARISSA_XMLHTTP_PROGID
= null;
94 if(!window
.XMLHttpRequest
){
96 * Emulate XMLHttpRequest
99 XMLHttpRequest = function() {
100 if(!_SARISSA_XMLHTTP_PROGID
){
101 _SARISSA_XMLHTTP_PROGID
= Sarissa
.pickRecentProgID(["Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"]);
103 return new ActiveXObject(_SARISSA_XMLHTTP_PROGID
);
106 // we dont need this anymore
107 //============================================
108 // Factory methods (IE)
109 //============================================
110 // see non-IE version
111 Sarissa
.getDomDocument = function(sUri
, sName
){
112 if(!_SARISSA_DOM_PROGID
){
113 _SARISSA_DOM_PROGID
= Sarissa
.pickRecentProgID(["Msxml2.DOMDocument.4.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"]);
115 var oDoc
= new ActiveXObject(_SARISSA_DOM_PROGID
);
116 // if a root tag name was provided, we need to load it in the DOM object
118 // create an artifical namespace prefix
119 // or reuse existing prefix if applicable
122 if(sName
.indexOf(":") > 1){
123 prefix
= sName
.substring(0, sName
.indexOf(":"));
124 sName
= sName
.substring(sName
.indexOf(":")+1);
126 prefix
= "a" + (_sarissa_iNsCounter
++);
129 // use namespaces if a namespace URI exists
131 oDoc
.loadXML('<' + prefix
+':'+sName
+ " xmlns:" + prefix
+ "=\"" + sUri
+ "\"" + " />");
133 oDoc
.loadXML('<' + sName
+ " />");
138 // see non-IE version
139 Sarissa
.getParseErrorText = function (oDoc
) {
140 var parseErrorText
= Sarissa
.PARSED_OK
;
141 if(oDoc
.parseError
.errorCode
!= 0){
142 parseErrorText
= "XML Parsing Error: " + oDoc
.parseError
.reason
+
143 "\nLocation: " + oDoc
.parseError
.url
+
144 "\nLine Number " + oDoc
.parseError
.line
+ ", Column " +
145 oDoc
.parseError
.linepos
+
146 ":\n" + oDoc
.parseError
.srcText
+
148 for(var i
= 0; i
< oDoc
.parseError
.linepos
;i
++){
149 parseErrorText
+= "-";
151 parseErrorText
+= "^\n";
153 else if(oDoc
.documentElement
== null){
154 parseErrorText
= Sarissa
.PARSED_EMPTY
;
156 return parseErrorText
;
158 // see non-IE version
159 Sarissa
.setXpathNamespaces = function(oDoc
, sNsSet
) {
160 oDoc
.setProperty("SelectionLanguage", "XPath");
161 oDoc
.setProperty("SelectionNamespaces", sNsSet
);
164 * Basic implementation of Mozilla's XSLTProcessor for IE.
165 * Reuses the same XSLT stylesheet for multiple transforms
168 XSLTProcessor = function(){
169 if(!_SARISSA_XSLTEMPLATE_PROGID
){
170 _SARISSA_XSLTEMPLATE_PROGID
= Sarissa
.pickRecentProgID(["Msxml2.XSLTemplate.4.0", "MSXML2.XSLTemplate.3.0"]);
172 this.template
= new ActiveXObject(_SARISSA_XSLTEMPLATE_PROGID
);
173 this.processor
= null;
176 * Imports the given XSLT DOM and compiles it to a reusable transform
177 * <b>Note:</b> If the stylesheet was loaded from a URL and contains xsl:import or xsl:include elements,it will be reloaded to resolve those
178 * @argument xslDoc The XSLT DOMDocument to import
180 XSLTProcessor
.prototype.importStylesheet = function(xslDoc
){
181 if(!_SARISSA_THREADEDDOM_PROGID
){
182 _SARISSA_THREADEDDOM_PROGID
= Sarissa
.pickRecentProgID(["MSXML2.FreeThreadedDOMDocument.4.0", "MSXML2.FreeThreadedDOMDocument.3.0"]);
183 _SARISSA_DOM_XMLWRITER
= Sarissa
.pickRecentProgID(["Msxml2.MXXMLWriter.4.0", "Msxml2.MXXMLWriter.3.0", "MSXML2.MXXMLWriter", "MSXML.MXXMLWriter", "Microsoft.XMLDOM"]);
185 xslDoc
.setProperty("SelectionLanguage", "XPath");
186 xslDoc
.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
187 // convert stylesheet to free threaded
188 var converted
= new ActiveXObject(_SARISSA_THREADEDDOM_PROGID
);
189 // make included/imported stylesheets work if exist and xsl was originally loaded from url
190 if(xslDoc
.url
&& xslDoc
.selectSingleNode("//xsl:*[local-name() = 'import' or local-name() = 'include']") != null){
191 converted
.async
= false;
192 converted
.load(xslDoc
.url
);
194 converted
.loadXML(xslDoc
.xml
);
196 converted
.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
197 var output
= converted
.selectSingleNode("//xsl:output");
198 this.outputMethod
= output
? output
.getAttribute("method") : "html";
199 this.template
.stylesheet
= converted
;
200 this.processor
= this.template
.createProcessor();
201 // (re)set default param values
206 * Transform the given XML DOM and return the transformation result as a new DOM document
207 * @argument sourceDoc The XML DOMDocument to transform
208 * @return The transformation result as a DOM Document
210 XSLTProcessor
.prototype.transformToDocument = function(sourceDoc
){
211 // fix for bug 1549749
212 if(_SARISSA_THREADEDDOM_PROGID
== "MSXML2.FreeThreadedDOMDocument.3.0"){
213 this.processor
.input
=sourceDoc
;
215 var outDoc
=new ActiveXObject(_SARISSA_DOM_PROGID
);
217 this.processor
.output
=outDoc
;
219 this.processor
.transform();
224 this.processor
.input
= sourceDoc
;
226 var outDoc
= new ActiveXObject(_SARISSA_DOM_XMLWRITER
);
228 this.processor
.output
= outDoc
;
230 this.processor
.transform();
232 var oDoc
= new ActiveXObject(_SARISSA_DOM_PROGID
);
234 oDoc
.loadXML(outDoc
.output
+"");
241 * Transform the given XML DOM and return the transformation result as a new DOM fragment.
242 * <b>Note</b>: The xsl:output method must match the nature of the owner document (XML/HTML).
243 * @argument sourceDoc The XML DOMDocument to transform
244 * @argument ownerDoc The owner of the result fragment
245 * @return The transformation result as a DOM Document
247 XSLTProcessor
.prototype.transformToFragment = function (sourceDoc
, ownerDoc
) {
248 this.processor
.input
= sourceDoc
;
249 this.processor
.transform();
250 var s
= this.processor
.output
;
251 var f
= ownerDoc
.createDocumentFragment();
252 if (this.outputMethod
== 'text') {
253 f
.appendChild(ownerDoc
.createTextNode(s
));
254 } else if (ownerDoc
.body
&& ownerDoc
.body
.innerHTML
) {
255 var container
= ownerDoc
.createElement('div');
256 container
.innerHTML
= s
;
257 while (container
.hasChildNodes()) {
258 f
.appendChild(container
.firstChild
);
262 var oDoc
= new ActiveXObject(_SARISSA_DOM_PROGID
);
263 if (s
.substring(0, 5) == '<?xml') {
264 s
= s
.substring(s
.indexOf('?>') + 2);
266 var xml
= ''.concat('<my>', s
, '</my>');
268 var container
= oDoc
.documentElement
;
269 while (container
.hasChildNodes()) {
270 f
.appendChild(container
.firstChild
);
277 * Set global XSLT parameter of the imported stylesheet
278 * @argument nsURI The parameter namespace URI
279 * @argument name The parameter base name
280 * @argument value The new parameter value
282 XSLTProcessor
.prototype.setParameter = function(nsURI
, name
, value
){
283 /* nsURI is optional but cannot be null */
285 this.processor
.addParameter(name
, value
, nsURI
);
287 this.processor
.addParameter(name
, value
);
289 /* update updated params for getParameter */
290 if(!this.paramsSet
[""+nsURI
]){
291 this.paramsSet
[""+nsURI
] = [];
293 this.paramsSet
[""+nsURI
][name
] = value
;
296 * Gets a parameter if previously set by setParameter. Returns null
298 * @argument name The parameter base name
299 * @argument value The new parameter value
300 * @return The parameter value if reviously set by setParameter, null otherwise
302 XSLTProcessor
.prototype.getParameter = function(nsURI
, name
){
304 if(this.paramsSet
[nsURI
] && this.paramsSet
[nsURI
][name
]){
305 return this.paramsSet
[nsURI
][name
];
310 }else{ /* end IE initialization, try to deal with real browsers now ;-) */
311 if(_SARISSA_HAS_DOM_CREATE_DOCUMENT
){
313 * <p>Ensures the document was loaded correctly, otherwise sets the
314 * parseError to -1 to indicate something went wrong. Internal use</p>
317 Sarissa
.__handleLoad__ = function(oDoc
){
318 Sarissa
.__setReadyState__(oDoc
, 4);
321 * <p>Attached by an event handler to the load event. Internal use.</p>
324 _sarissa_XMLDocument_onload = function(){
325 Sarissa
.__handleLoad__(this);
328 * <p>Sets the readyState property of the given DOM Document object.
331 * @argument oDoc the DOM Document object to fire the
332 * readystatechange event
333 * @argument iReadyState the number to change the readystate property to
335 Sarissa
.__setReadyState__ = function(oDoc
, iReadyState
){
336 oDoc
.readyState
= iReadyState
;
337 oDoc
.readystate
= iReadyState
;
338 if (oDoc
.onreadystatechange
!= null &&
339 typeof oDoc
.onreadystatechange
== "function") {
340 oDoc
.onreadystatechange();
343 Sarissa
.getDomDocument = function(sUri
, sName
){
344 var oDoc
= document
.implementation
.createDocument(sUri
?sUri
:null, sName
?sName
:null, null);
345 if(!oDoc
.onreadystatechange
){
348 * <p>Emulate IE's onreadystatechange attribute</p>
350 oDoc
.onreadystatechange
= null;
352 if(!oDoc
.readyState
){
354 * <p>Emulates IE's readyState property, which always gives an integer from 0 to 4:</p>
355 * <ul><li>1 == LOADING,</li>
356 * <li>2 == LOADED,</li>
357 * <li>3 == INTERACTIVE,</li>
358 * <li>4 == COMPLETED</li></ul>
362 oDoc
.addEventListener("load", _sarissa_XMLDocument_onload
, false);
365 if(window
.XMLDocument
){
367 //if(window.XMLDocument) , now mainly for opera
368 }// TODO: check if the new document has content before trying to copynodes, check for error handling in DOM 3 LS
369 else if(_SARISSA_HAS_DOM_FEATURE
&& (typeof Document
!= 'undefined') && !Document
.prototype.load
&& document
.implementation
.hasFeature('LS', '3.0')){
370 //Opera 9 may get the XPath branch which gives creates XMLDocument, therefore it doesn't reach here which is good
372 * <p>Factory method to obtain a new DOM Document object</p>
373 * @argument sUri the namespace of the root node (if any)
374 * @argument sUri the local name of the root node (if any)
375 * @returns a new DOM Document
377 Sarissa
.getDomDocument = function(sUri
, sName
){
378 var oDoc
= document
.implementation
.createDocument(sUri
?sUri
:null, sName
?sName
:null, null);
383 Sarissa
.getDomDocument = function(sUri
, sName
){
384 var oDoc
= document
.implementation
.createDocument(sUri
?sUri
:null, sName
?sName
:null, null);
385 // looks like safari does not create the root element for some unknown reason
386 if(oDoc
&& (sUri
|| sName
) && !oDoc
.documentElement
){
387 oDoc
.appendChild(oDoc
.createElementNS(sUri
, sName
));
392 };//if(_SARISSA_HAS_DOM_CREATE_DOCUMENT)
394 //==========================================
396 //==========================================
397 if(!window
.DOMParser
){
398 if(_SARISSA_IS_SAFARI
){
400 * DOMParser is a utility class, used to construct DOMDocuments from XML strings
403 DOMParser = function() { };
405 * Construct a new DOM Document from the given XMLstring
406 * @param sXml the given XML string
407 * @param contentType the content type of the document the given string represents (one of text/xml, application/xml, application/xhtml+xml).
408 * @return a new DOM Document from the given XML string
410 DOMParser
.prototype.parseFromString = function(sXml
, contentType
){
411 var xmlhttp
= new XMLHttpRequest();
412 xmlhttp
.open("GET", "data:text/xml;charset=utf-8," + encodeURIComponent(sXml
), false);
414 return xmlhttp
.responseXML
;
416 }else if(Sarissa
.getDomDocument
&& Sarissa
.getDomDocument() && Sarissa
.getDomDocument(null, "bar").xml
){
417 DOMParser = function() { };
418 DOMParser
.prototype.parseFromString = function(sXml
, contentType
){
419 var doc
= Sarissa
.getDomDocument();
426 if(!document
.importNode
&& _SARISSA_IS_IE
){
429 * Implementation of importNode for the context window document in IE
430 * @param oNode the Node to import
431 * @param bChildren whether to include the children of oNode
432 * @returns the imported node for further use
434 document
.importNode = function(oNode
, bChildren
){
435 var tmp
= document
.createElement("div");
437 tmp
.innerHTML
= oNode
.xml
? oNode
.xml
: oNode
.outerHTML
;
439 tmp
.innerHTML
= oNode
.xml
? oNode
.cloneNode(false).xml
: oNode
.cloneNode(false).outerHTML
;
441 return tmp
.getElementsByTagName("*")[0];
445 if(!Sarissa
.getParseErrorText
){
447 * <p>Returns a human readable description of the parsing error. Usefull
448 * for debugging. Tip: append the returned error string in a <pre>
449 * element if you want to render it.</p>
450 * <p>Many thanks to Christian Stocker for the initial patch.</p>
451 * @argument oDoc The target DOM document
452 * @returns The parsing error description of the target Document in
453 * human readable form (preformated text)
455 Sarissa
.getParseErrorText = function (oDoc
){
456 var parseErrorText
= Sarissa
.PARSED_OK
;
457 if(!oDoc
.documentElement
){
458 parseErrorText
= Sarissa
.PARSED_EMPTY
;
459 } else if(oDoc
.documentElement
.tagName
== "parsererror"){
460 parseErrorText
= oDoc
.documentElement
.firstChild
.data
;
461 parseErrorText
+= "\n" + oDoc
.documentElement
.firstChild
.nextSibling
.firstChild
.data
;
462 } else if(oDoc
.getElementsByTagName("parsererror").length
> 0){
463 var parsererror
= oDoc
.getElementsByTagName("parsererror")[0];
464 parseErrorText
= Sarissa
.getText(parsererror
, true)+"\n";
465 } else if(oDoc
.parseError
&& oDoc
.parseError
.errorCode
!= 0){
466 parseErrorText
= Sarissa
.PARSED_UNKNOWN_ERROR
;
468 return parseErrorText
;
471 Sarissa
.getText = function(oNode
, deep
){
473 var nodes
= oNode
.childNodes
;
474 for(var i
=0; i
< nodes
.length
; i
++){
476 var nodeType
= node
.nodeType
;
477 if(nodeType
== Node
.TEXT_NODE
|| nodeType
== Node
.CDATA_SECTION_NODE
){
479 } else if(deep
== true &&
480 (nodeType
== Node
.ELEMENT_NODE
||
481 nodeType
== Node
.DOCUMENT_NODE
||
482 nodeType
== Node
.DOCUMENT_FRAGMENT_NODE
)){
483 s
+= Sarissa
.getText(node
, true);
488 if(!window
.XMLSerializer
&&
489 Sarissa
.getDomDocument
&&
490 Sarissa
.getDomDocument("","foo", null).xml
){
492 * Utility class to serialize DOM Node objects to XML strings
495 XMLSerializer = function(){};
497 * Serialize the given DOM Node to an XML string
498 * @param oNode the DOM Node to serialize
500 XMLSerializer
.prototype.serializeToString = function(oNode
) {
506 * strips tags from a markup string
508 Sarissa
.stripTags = function (s
) {
509 return s
.replace(/<[^>]+>/g,"");
512 * <p>Deletes all child nodes of the given node</p>
513 * @argument oNode the Node to empty
515 Sarissa
.clearChildNodes = function(oNode
) {
516 // need to check for firstChild due to opera 8 bug with hasChildNodes
517 while(oNode
.firstChild
) {
518 oNode
.removeChild(oNode
.firstChild
);
522 * <p> Copies the childNodes of nodeFrom to nodeTo</p>
523 * <p> <b>Note:</b> The second object's original content is deleted before
524 * the copy operation, unless you supply a true third parameter</p>
525 * @argument nodeFrom the Node to copy the childNodes from
526 * @argument nodeTo the Node to copy the childNodes to
527 * @argument bPreserveExisting whether to preserve the original content of nodeTo, default is false
529 Sarissa
.copyChildNodes = function(nodeFrom
, nodeTo
, bPreserveExisting
) {
530 if((!nodeFrom
) || (!nodeTo
)){
531 throw "Both source and destination nodes must be provided";
533 if(!bPreserveExisting
){
534 Sarissa
.clearChildNodes(nodeTo
);
536 var ownerDoc
= nodeTo
.nodeType
== Node
.DOCUMENT_NODE
? nodeTo
: nodeTo
.ownerDocument
;
537 var nodes
= nodeFrom
.childNodes
;
538 if(typeof(ownerDoc
.importNode
) != "undefined") {
539 for(var i
=0;i
< nodes
.length
;i
++) {
540 nodeTo
.appendChild(ownerDoc
.importNode(nodes
[i
], true));
543 for(var i
=0;i
< nodes
.length
;i
++) {
544 nodeTo
.appendChild(nodes
[i
].cloneNode(true));
550 * <p> Moves the childNodes of nodeFrom to nodeTo</p>
551 * <p> <b>Note:</b> The second object's original content is deleted before
552 * the move operation, unless you supply a true third parameter</p>
553 * @argument nodeFrom the Node to copy the childNodes from
554 * @argument nodeTo the Node to copy the childNodes to
555 * @argument bPreserveExisting whether to preserve the original content of nodeTo, default is
557 Sarissa
.moveChildNodes = function(nodeFrom
, nodeTo
, bPreserveExisting
) {
558 if((!nodeFrom
) || (!nodeTo
)){
559 throw "Both source and destination nodes must be provided";
561 if(!bPreserveExisting
){
562 Sarissa
.clearChildNodes(nodeTo
);
564 var nodes
= nodeFrom
.childNodes
;
565 // if within the same doc, just move, else copy and delete
566 if(nodeFrom
.ownerDocument
== nodeTo
.ownerDocument
){
567 while(nodeFrom
.firstChild
){
568 nodeTo
.appendChild(nodeFrom
.firstChild
);
571 var ownerDoc
= nodeTo
.nodeType
== Node
.DOCUMENT_NODE
? nodeTo
: nodeTo
.ownerDocument
;
572 if(ownerDoc
.importNode
) {
573 for(var i
=0;i
< nodes
.length
;i
++) {
574 nodeTo
.appendChild(ownerDoc
.importNode(nodes
[i
], true));
577 for(var i
=0;i
< nodes
.length
;i
++) {
578 nodeTo
.appendChild(nodes
[i
].cloneNode(true));
581 Sarissa
.clearChildNodes(nodeFrom
);
586 * <p>Serialize any object to an XML string. All properties are serialized using the property name
587 * as the XML element name. Array elements are rendered as <code>array-item</code> elements,
588 * using their index/key as the value of the <code>key</code> attribute.</p>
589 * @argument anyObject the object to serialize
590 * @argument objectName a name for that object
591 * @return the XML serializationj of the given object as a string
593 Sarissa
.xmlize = function(anyObject
, objectName
, indentSpace
){
594 indentSpace
= indentSpace
?indentSpace
:'';
595 var s
= indentSpace
+ '<' + objectName
+ '>';
597 if(!(anyObject
instanceof Object
) || anyObject
instanceof Number
||
598 anyObject
instanceof String
|| anyObject
instanceof Boolean
||
599 anyObject
instanceof Date
){
600 s
+= Sarissa
.escape(""+anyObject
);
604 var isArrayItem
= anyObject
instanceof Array
;
605 for(var name
in anyObject
){
606 s
+= Sarissa
.xmlize(anyObject
[name
], (isArrayItem
?"array-item key=\""+name
+"\"":name
), indentSpace
+ " ");
610 return (s
+= (objectName
.indexOf(' ')!=-1?"</array-item>\n":"</" + objectName
+ ">\n"));
614 * Escape the given string chacters that correspond to the five predefined XML entities
615 * @param sXml the string to escape
617 Sarissa
.escape = function(sXml
){
618 return sXml
.replace(/&/g
, "&").
619 replace(/</g
, "<").
620 replace(/>/g
, ">").
621 replace(/"/g, ""
;").
622 replace(/'/g, "&apos
;");
626 * Unescape the given string. This turns the occurences of the predefined XML
627 * entities to become the characters they represent correspond to the five predefined XML entities
628 * @param sXml the string to unescape
630 Sarissa.unescape = function(sXml){
631 return sXml.replace(/'/g,"'").
632 replace(/"/g,"\"").
633 replace(/>/g,">").
634 replace(/</g,"<").
635 replace(/&/g,"&");