1 /* 2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. 3 For licensing, see LICENSE.html or http://ckeditor.com/license 4 */ 5 6 /** 7 * @fileOverview Defines the {@link CKEDITOR.xml} class, which represents a 8 * loaded XML document. 9 */ 10 11 /** 12 * Represents a loaded XML document. 13 * @constructor 14 * @param {object|string} xmlObjectOrData A native XML (DOM document) object or 15 * a string containing the XML definition to be loaded. 16 * @example 17 * var xml = <b>new CKEDITOR.xml( '<books><book title="My Book" /></books>' )</b>; 18 */ 19 CKEDITOR.xml = function( xmlObjectOrData ) 20 { 21 var baseXml = null; 22 23 if ( typeof xmlObjectOrData == 'object' ) 24 baseXml = xmlObjectOrData; 25 else 26 { 27 var data = ( xmlObjectOrData || '' ).replace( / /g, '\xA0' ); 28 if ( window.DOMParser ) 29 baseXml = (new DOMParser()).parseFromString( data, 'text/xml' ); 30 else if ( window.ActiveXObject ) 31 { 32 try { baseXml = new ActiveXObject( 'MSXML2.DOMDocument' ); } 33 catch(e) 34 { 35 try { baseXml = new ActiveXObject( 'Microsoft.XmlDom' ); } catch(e) {} 36 } 37 38 if ( baseXml ) 39 { 40 baseXml.async = false; 41 baseXml.resolveExternals = false; 42 baseXml.validateOnParse = false; 43 baseXml.loadXML( data ); 44 } 45 } 46 } 47 48 /** 49 * The native XML (DOM document) used by the class instance. 50 * @type object 51 * @example 52 */ 53 this.baseXml = baseXml; 54 }; 55 56 CKEDITOR.xml.prototype = 57 { 58 /** 59 * Get a single node from the XML document, based on a XPath query. 60 * @param {String} xpath The XPath query to execute. 61 * @param {Object} [contextNode] The XML DOM node to be used as the context 62 * for the XPath query. The document root is used by default. 63 * @returns {Object} A XML node element or null if the query has no results. 64 * @example 65 * // Create the XML instance. 66 * var xml = new CKEDITOR.xml( '<list><item id="test1" /><item id="test2" /></list>' ); 67 * // Get the first <item> node. 68 * var itemNode = <b>xml.selectSingleNode( 'list/item' )</b>; 69 * // Alert "item". 70 * alert( itemNode.nodeName ); 71 */ 72 selectSingleNode : function( xpath, contextNode ) 73 { 74 var baseXml = this.baseXml; 75 76 if ( contextNode || ( contextNode = baseXml ) ) 77 { 78 if ( CKEDITOR.env.ie || contextNode.selectSingleNode ) // IE 79 return contextNode.selectSingleNode( xpath ); 80 else if ( baseXml.evaluate ) // Others 81 { 82 var result = baseXml.evaluate( xpath, contextNode, null, 9, null); 83 return ( result && result.singleNodeValue ) || null; 84 } 85 } 86 87 return null; 88 }, 89 90 /** 91 * Gets a list node from the XML document, based on a XPath query. 92 * @param {String} xpath The XPath query to execute. 93 * @param {Object} [contextNode] The XML DOM node to be used as the context 94 * for the XPath query. The document root is used by default. 95 * @returns {ArrayLike} An array containing all matched nodes. The array will 96 * be empty if the query has no results. 97 * @example 98 * // Create the XML instance. 99 * var xml = new CKEDITOR.xml( '<list><item id="test1" /><item id="test2" /></list>' ); 100 * // Get the first <item> node. 101 * var itemNodes = xml.selectSingleNode( 'list/item' ); 102 * // Alert "item" twice, one for each <item>. 103 * for ( var i = 0 ; i < itemNodes.length ; i++ ) 104 * alert( itemNodes[i].nodeName ); 105 */ 106 selectNodes : function( xpath, contextNode ) 107 { 108 var baseXml = this.baseXml, 109 nodes = []; 110 111 if ( contextNode || ( contextNode = baseXml ) ) 112 { 113 if ( CKEDITOR.env.ie || contextNode.selectNodes ) // IE 114 return contextNode.selectNodes( xpath ); 115 else if ( baseXml.evaluate ) // Others 116 { 117 var result = baseXml.evaluate( xpath, contextNode, null, 5, null); 118 119 if ( result ) 120 { 121 var node; 122 while( ( node = result.iterateNext() ) ) 123 nodes.push( node ); 124 } 125 } 126 } 127 128 return nodes; 129 }, 130 131 /** 132 * Gets the string representation of hte inner contents of a XML node, 133 * based on a XPath query. 134 * @param {String} xpath The XPath query to execute. 135 * @param {Object} [contextNode] The XML DOM node to be used as the context 136 * for the XPath query. The document root is used by default. 137 * @returns {String} The textual representation of the inner contents of 138 * the node or null if the query has no results. 139 * @example 140 * // Create the XML instance. 141 * var xml = new CKEDITOR.xml( '<list><item id="test1" /><item id="test2" /></list>' ); 142 * // Alert "<item id="test1" /><item id="test2" />". 143 * alert( xml.getInnerXml( 'list' ) ); 144 */ 145 getInnerXml : function( xpath, contextNode ) 146 { 147 var node = this.selectSingleNode( xpath, contextNode ), 148 xml = []; 149 if ( node ) 150 { 151 node = node.firstChild; 152 while ( node ) 153 { 154 if ( node.xml ) // IE 155 xml.push( node.xml ); 156 else if ( window.XMLSerializer ) // Others 157 xml.push( ( new XMLSerializer() ).serializeToString( node ) ); 158 159 node = node.nextSibling; 160 } 161 } 162 163 return xml.length ? xml.join( '' ) : null; 164 } 165 }; 166