Утилитный класс парсинга xml (AS2)
Как - то (вчера), мне надоели жутко разветвлённые конструкции switch/ case при парсинге xml ( в чужом коде). Так как мне необходимо было переписать парсер, то я решил избавится от этих надоедливых конструкций
было:
while(xmlPos != null) { xmlName = xmlPos.nodeName.toLowerCase(); xmlAttr = xmlPos.attributes; if(xmlName != null) { //Output("<"+xmlName+"> was found..."); // нашли реальный узел switch(xmlName) { case "server" : switch(xmlAttr["command"]) { case "start" : case "bet" : case "chance" : case "bonus" : case "pong" : case "miniprize_games" : case "swim_scatters" : delete gameResult; gameResult = new Object(); gameResult["status"] = xmlAttr["status"]; //Output("\t\t server command = " + xmlAttr["command"] + " found."); /* 20091024: при получении статуса EXIT или EXCESS */ if (gameResult["status"] == "exit" || gameResult["status"] == "excess") { mInterface.sendDefaultDebugInfo(); // шлем дефолтное сообщение с логом mInterface.mButtonExit.DoRelease(); // выходим в лобби this._parent.mCommon.mWins.mWinMsg.Show({text:GetText("text_error_sorry")}); // показываем окно с извинениями } /* --- */ break; case "match" : if(xmlAttr["status"]=="ok") { if(mTestNoMatch.vis) mTestNoMatch.Hide(); // если начался новый турнир if(mMatch.IsOver) { mMatch.IsOver = false; mMatch.Timeout = false; //mGame.SetupInterface("gamewait2"); } } break; case '': case undefined : if(xmlAttr["status"].split('_').shift()=="match") { if(!mMatch) mMatch = {}; if(!mMatch.stack) mMatch.stack = {}; mMatch.stack[xmlAttr["status"]] = 1; } break; default : mTestNoMatch.Show(); } break; case "reel" : if (Vars.multiTapeReel != 1) { HC.ReelsLen["reel_"+xmlAttr["id"]] = int(xmlAttr["length"]); mReels.ReelsLen["reel_"+xmlAttr["id"]] = int(xmlAttr["length"]); mReels.ReelsLayout["reel_"+xmlAttr["id"]] = xmlAttr["layout"]; } break; case "reels": case "reels2": case "reels3": mReels.api.reelsLayoutAdd ({ xml_name:xmlName, xml_data:xmlPos }); //reel_set break; case "shift" : gameResult["server_shift"] = xmlAttr["server"]; gameResult["user_shift"] = xmlAttr["user"] if(start_shift == undefined) var start_shift = gameResult["server_shift"]; for(i = 1 ; i <= xmlAttr["server"].split(",").length; i++){ gameResult["reel_"+i] = xmlAttr["server"].split(",")[i-1]; } break; ...итп итд
/** * Вложенные блоки в основной xml * @param xml */ private function parseServerNodes(xml:XMLNode):Void { trace("SlotParser.parseServerNodes > xml : " + xml); TagParser.add([ServerTag.SLOT, ServerTag.SLOTS], parseSlots,this); TagParser.add(ServerTag.SHIFT, parseShift,this); TagParser.add(ServerTag.PLAYER, parsePlayer,this); // парсим с очисткой стека парсеров TagParser.parse(xml,true); } /** * Обработчик блока slot * @param xml */ private function parseSlots(xml:XMLNode):Void { trace("SlotParser.parseSlots > xml : " + xml); TagParser.add(SlotsTag.COMBINATIONS, parseCombinations, this); //TagParser.add(SlotsTag.REEL, parseReel, this); TagParser.add([SlotsTag.REELS, SlotsTag.REELS2,SlotsTag.REELS3], parseReels, this); TagParser.add(SlotsTag.PAYLINES, parsePaylines, this); TagParser.add(SlotsTag.SYMBOLS, parseSymbol, this); TagParser.parse(xml); }
код в общем количестве строк и файлов (был вообще в одном инклуд файле на 5000 строк) может и станет длинее, но понятнее 100 пудово!
Вот собственно и сам класс парсинга:
/** * Утилитный класс парсинга XML. * !ВНИМАНИЕ! Ипользуются глобальные статичные методы. * @author k0t0vich */ class ru.globo.utils.TagParser { static private var _functionListsArray:Array=[{}]; //static private var _currentParsersList:Object = {}; static private var _instance:TagParser; static private var listCounter:Number = 0; static public function get _currentParsersList():Object { if (_functionListsArray[listCounter] == undefined) _functionListsArray[listCounter] = {}; return _functionListsArray[listCounter]; } /** * Добавить ф-цию - xml парсер по имени нода (массиву имён). * Добавляется в текущий список. * @param tags строка или массив строк * @param parseFunction ф-ция вида func(xmlNode:XMLNode) * @param scope объект для вызова ф-ции */ static public function add(tags, parseFunction:Function,scope:Object) { if (typeof(tags) == "object") { for (var name:String in tags) { var tag = tags[name]; if (typeof(tag) == "string") addOne(tag, parseFunction, scope); } } else if (typeof(tags) == "string") { addOne(tags, parseFunction, scope); } } /** * Добавить парсер по строке * @param tag строго строка * @param parseFunction ф-ция вида func(xmlNode:XMLNode) * @param scope объект для вызова ф-ции */ static private function addOne(tag:String, parseFunction:Function, scope:Object) { //trace("TagParser.addOne > tag : " + tag + ", parseFunction : " + parseFunction + ", scope : " + scope+" listCounter=" + listCounter); _currentParsersList[tag] = {func:parseFunction,scope:scope}; } /** * Очистить список парсеров */ static public function clear():Void { //trace("TagParser.clear"); _functionListsArray = [ { } ]; listCounter = 0; } /** * Распарсить xml по имени нода. * Вызов этой ф-ции прекращает ввод парсеров для этой xml, при следующем add - парсеры добавятся в другой список. * @param xml xmlNode для парсинга * @param clearAfterParse флаг очистки списков. для xml - являющейся корневой - необходимо передавать true */ static public function parse(xml:XMLNode, clearAfterParse:Boolean) { // запоминаем счётчик - индекс, чтоб использовать список парсеров для данного блока в случае вложенных парсеров var counter:Number = listCounter; listCounter++; var len:Number = xml.childNodes.length; for (var i:Number = 0; i < len; i++) { var xmlNode = xml.childNodes[i]; var xmlName:String = xmlNode.nodeName.toLowerCase(); var item = _functionListsArray[counter][xmlName]; // если есть соответствия то вызываем ф-цию if (item != undefined) { var func:Function = item.func; var scope = item.scope; func.call(scope,xmlNode); } } // очищаем список. если надо( по умолчанию не очищаем) или если это корневой xml if (clearAfterParse || counter==0) clear(); } }
Всего комментариев 0
Комментарии
Последние записи от Котяра
- Страх и ненависть в Нью-Дели или сборка мультипака для arm7 и x86 c Adobe AIR 14 в FB (16.06.2014)
- Нативный EventDispatcher в старлинге (27.11.2013)
- Нужны ошибки компиляции при создании экземпляра синглетона извне? Запросто! (13.09.2013)
- ARP - новый формат упаковки ресурсов (07.02.2013)
- DropShadowFilter и GlowFilter в Starling (16.01.2013)