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 or you forgot to preload the 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.Loader.getInstance().onResLoaded(); 194 cc.log("cocos2d:There was a problem retrieving the xml data:" + xmlhttp.statusText); 195 } 196 } 197 }; 198 // load xml 199 xmlhttp.open("GET", filePath, true); 200 xmlhttp.send(null); 201 } else 202 throw "cocos2d:Your browser does not support XMLHTTP."; 203 }, 204 205 /** 206 * Unload the preloaded plist from xmlList 207 * @param {String} filePath 208 */ 209 unloadPlist: function (filePath) { 210 if (this._xmlDict.hasOwnProperty(filePath)) 211 delete this._xmlDict[filePath]; 212 }, 213 214 /** 215 * get filename from filepath 216 * @param {String} filePath 217 * @return {String} 218 */ 219 getName: function (filePath) { 220 var startPos = filePath.lastIndexOf("/", filePath.length) + 1; 221 var endPos = filePath.lastIndexOf(".", filePath.length); 222 return filePath.substring(startPos, endPos); 223 }, 224 225 /** 226 * get file extension name from filepath 227 * @param {String} filePath 228 * @return {String} 229 */ 230 getExt: function (filePath) { 231 var startPos = filePath.lastIndexOf(".", filePath.length) + 1; 232 return filePath.substring(startPos, filePath.length); 233 }, 234 235 /** 236 * get value by key from xmlList 237 * @param {String} key 238 * @return {String} xml content 239 */ 240 getList: function (key) { 241 if (this._xmlDict != null) { 242 return this._xmlDict[key]; 243 } 244 return null; 245 } 246 }); 247 248 /** 249 * get a singleton SAX parser 250 * @function 251 * @return {cc.SAXParser} 252 */ 253 cc.SAXParser.getInstance = function () { 254 if (!this._instance) { 255 this._instance = new cc.SAXParser(); 256 } 257 return this._instance; 258 }; 259 260 cc.SAXParser._instance = null;