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