1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 Copyright (c) 2008-2010 Ricardo Quesada 4 Copyright (c) 2011 Zynga Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 /** 28 * a SAX Parser 29 * @class 30 * @extends cc.Class 31 */ 32 cc.SAXParser = cc.Class.extend(/** @lends cc.SAXParser# */{ 33 xmlDoc: null, 34 _parser: null, 35 _xmlDict: null, 36 _isSupportDOMParser: null, 37 38 ctor: function () { 39 this._xmlDict = {}; 40 41 if (window.DOMParser) { 42 this._isSupportDOMParser = true; 43 this._parser = new DOMParser(); 44 } else { 45 this._isSupportDOMParser = false; 46 } 47 }, 48 49 /** 50 * parse a xml from a string (xmlhttpObj.responseText) 51 * @param {String} textxml plist xml contents 52 * @return {Array} plist object array 53 */ 54 parse: function (textxml) { 55 var path = textxml; 56 textxml = this.getList(textxml); 57 58 var xmlDoc = this._parserXML(textxml, path); 59 60 var plist = xmlDoc.documentElement; 61 if (plist.tagName != 'plist') 62 throw "cocos2d: " + path + " is not a plist file"; 63 64 // Get first real node 65 var node = null; 66 for (var i = 0, len = plist.childNodes.length; i < len; i++) { 67 node = plist.childNodes[i]; 68 if (node.nodeType == 1) 69 break 70 } 71 xmlDoc = null; 72 73 return this._parseNode(node); 74 }, 75 76 /** 77 * parse a tilemap xml from a string (xmlhttpObj.responseText) 78 * @param {String} textxml tilemap xml content 79 * @return {Document} xml document 80 */ 81 tmxParse: function (textxml, isXMLString) { 82 if ((isXMLString == null) || (isXMLString === false)) 83 textxml = this.getList(textxml); 84 85 return this._parserXML(textxml); 86 }, 87 88 _parserXML: function (textxml, path) { 89 // get a reference to the requested corresponding xml file 90 var xmlDoc; 91 if (this._isSupportDOMParser) { 92 xmlDoc = this._parser.parseFromString(textxml, "text/xml"); 93 } else { 94 // Internet Explorer (untested!) 95 xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); 96 xmlDoc.async = "false"; 97 xmlDoc.loadXML(textxml); 98 } 99 100 if (xmlDoc == null) 101 cc.log("cocos2d:xml " + path + " not found!"); 102 103 return xmlDoc; 104 }, 105 106 _parseNode: function (node) { 107 var data = null; 108 switch (node.tagName) { 109 case 'dict': 110 data = this._parseDict(node); 111 break; 112 case 'array': 113 data = this._parseArray(node); 114 break; 115 case 'string': 116 if (node.childNodes.length == 1) 117 data = node.firstChild.nodeValue; 118 else { 119 //handle Firefox's 4KB nodeValue limit 120 data = ""; 121 for (var i = 0; i < node.childNodes.length; i++) 122 data += node.childNodes[i].nodeValue; 123 } 124 break; 125 case 'false': 126 data = false; 127 break; 128 case 'true': 129 data = true; 130 break; 131 case 'real': 132 data = parseFloat(node.firstChild.nodeValue); 133 break; 134 case 'integer': 135 data = parseInt(node.firstChild.nodeValue, 10); 136 break; 137 } 138 139 return data; 140 }, 141 142 _parseArray: function (node) { 143 var data = []; 144 for (var i = 0, len = node.childNodes.length; i < len; i++) { 145 var child = node.childNodes[i]; 146 if (child.nodeType != 1) 147 continue; 148 data.push(this._parseNode(child)); 149 } 150 return data; 151 }, 152 153 _parseDict: function (node) { 154 var data = {}; 155 156 var key = null; 157 for (var i = 0, len = node.childNodes.length; i < len; i++) { 158 var child = node.childNodes[i]; 159 if (child.nodeType != 1) 160 continue; 161 162 // Grab the key, next noe should be the value 163 if (child.tagName == 'key') 164 key = child.firstChild.nodeValue; 165 else 166 data[key] = this._parseNode(child); // Parse the value node 167 } 168 return data; 169 }, 170 171 /** 172 * Preload plist file 173 * @param {String} filePath 174 */ 175 preloadPlist: function (filePath) { 176 filePath = cc.FileUtils.getInstance().fullPathForFilename(filePath); 177 178 if (window.XMLHttpRequest) { 179 var xmlhttp = new XMLHttpRequest(); 180 if (xmlhttp.overrideMimeType) 181 xmlhttp.overrideMimeType('text/xml'); 182 } 183 184 if (xmlhttp != null) { 185 var that = this; 186 xmlhttp.onreadystatechange = function () { 187 if (xmlhttp.readyState == 4) { 188 if (xmlhttp.responseText) { 189 cc.Loader.getInstance().onResLoaded(); 190 that._xmlDict[filePath] = xmlhttp.responseText; 191 xmlhttp = null; 192 } else 193 cc.Assert("cocos2d:There was a problem retrieving the xml data:" + xmlhttp.statusText); 194 } 195 }; 196 // load xml 197 xmlhttp.open("GET", filePath, true); 198 xmlhttp.send(null); 199 } else 200 cc.Assert("cocos2d:Your browser does not support XMLHTTP."); 201 }, 202 203 /** 204 * Unload the preloaded plist from xmlList 205 * @param {String} filePath 206 */ 207 unloadPlist: function (filePath) { 208 if (this._xmlDict.hasOwnProperty(filePath)) 209 delete this._xmlDict[filePath]; 210 }, 211 212 /** 213 * get filename from filepath 214 * @param {String} filePath 215 * @return {String} 216 */ 217 getName: function (filePath) { 218 var startPos = filePath.lastIndexOf("/", filePath.length) + 1; 219 var endPos = filePath.lastIndexOf(".", filePath.length); 220 return filePath.substring(startPos, endPos); 221 }, 222 223 /** 224 * get file extension name from filepath 225 * @param {String} filePath 226 * @return {String} 227 */ 228 getExt: function (filePath) { 229 var startPos = filePath.lastIndexOf(".", filePath.length) + 1; 230 return filePath.substring(startPos, filePath.length); 231 }, 232 233 /** 234 * get value by key from xmlList 235 * @param {String} key 236 * @return {String} xml content 237 */ 238 getList: function (key) { 239 if (this._xmlDict != null) { 240 return this._xmlDict[key]; 241 } 242 return null; 243 } 244 }); 245 246 /** 247 * get a singleton SAX parser 248 * @function 249 * @return {cc.SAXParser} 250 */ 251 cc.SAXParser.getInstance = function () { 252 if (!this._instance) { 253 this._instance = new cc.SAXParser(); 254 } 255 return this._instance; 256 }; 257 258 cc.SAXParser._instance = null;