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