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