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