Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 1.0/2.0 (http://www.flasher.ru/forum/forumdisplay.php?f=93)
-   -   Parse XML с неограниченной вложенностью (http://www.flasher.ru/forum/showthread.php?t=104299)

Ведьмак 22.11.2007 16:58

Parse XML с неограниченной вложенностью
 
Всем, доброго дня!

Есть XML типа
Код:

<parent>
  <text></text>
</parent>
<parent>
  <text></text>
  <sub>
      <text></text>
  </sub>
</parent>
<parent>
  <text></text>
  <sub>
      <text></text>
      <sub>
        <text></text>
      </sub>
  </sub>
</parent> ...

этих SUB в SUB может быт неогранниченное колличество.. Этакое древо..

Родскажите как это лучше распарсить в Flash? Что-то я совсем запутался в массивах, блин...

Fernando Costa 22.11.2007 17:28

ну если неограниченное дерево то рекурсией обходи

Ведьмак 22.11.2007 17:36

я думал, что от этого тут не убежать, да и при обработке конечного массива тоже нужно будет его раскручивать рекурсивно..

можно с этого момента по-подробнее или пример? )

Fernando Costa 22.11.2007 17:50

вот тут подобное обсуждалось: http://flasher.ru/forum/showthread.php?t=88954

Ведьмак 22.11.2007 18:33

спасибо.. только ему не предложили рабочего варианта, сказали только что вторая рекурсия лишня.. и в конце код также не рабочий..

вопрос еще актуален)

wvxvw 22.11.2007 18:39

ХМЛ парсится уже прямо при создании. Зачем его еще куда-то во что-то парсить?

telit 22.11.2007 18:40

Код:

XML.prototype.makeObj = function(xObj, obj) {
        //----- Initialise objects
        if (xObj == null) {
                xObj = this;
        }
        if (obj == null) {
                obj = {};
        }
        var a, c, nName, nType, nValue, cCount;
        //----- Add attributes to the object
        for (a in xObj.attributes) {
                obj[a] = xObj.attributes[a]
        }
        //----- Build child nodes
        for (c in xObj.childNodes) {
                nName = xObj.childNodes[c].nodeName;
                nType = xObj.childNodes[c].nodeType;
                nValue = xObj.childNodes[c].nodeValue;
                if (nType == 3) {
                        obj._value = nValue;
                        obj._type = 'text';
                }
                if (nType == 1 && nName != null) {
                        if (obj[nName] == null) {
                                obj[nName] = this.makeObj(xObj.childNodes[c], {});
                        } else if (obj[nName]._type != 'array') {
                                obj[nName] = [obj[nName]];
                                obj[nName]._type = 'array';
                        }
                        if (obj[nName]._type == 'array') {
                                obj[nName].unshift(this.makeObj(xObj.childNodes[c], {}));
                        }
                }
        }
        // Return object
        return obj;
};


Ведьмак 22.11.2007 18:44

2 wvxvw: XML внешний..
2 telit: спасибо конечно... ты хочешь, чтобы у меня моск взорвался? или пару комментов уже рука не поднялась писать? хоть что передается в функцию ( xObj, obj)?

wvxvw 22.11.2007 18:48

Во флеше все ХМЛи одинаковые %) они не бывают внешними или внутренними =)
Это значит, что если вы дождались ХML.onLoad - вы его уже 1 раз отпарсили. Лучше, чем сам Флеш вы это вряд ли сделаете, ну уж не быстрее, это точно =)

Ведьмак 22.11.2007 18:53

2 wvxvw: понял идею)) мне нужно обойти весь XML и перегнать инфорамцию во что-то с чем дальше можно удобны работать (массив и .т.д.)

2 telit: еще раз спасибо

wvxvw 22.11.2007 19:09

http://flasher.ru/forum/showthread.php?t=103255
Ну вот тогда еще 1 линк до кучи.

Ведьмак 23.11.2007 14:54

2 Telit: стреманулся насчет вашего кода по тому, что он слишком сложный для подобной задачи.. посидел пару часов и сделал следующий рабочий вариант:

ИСХОДНЫЙ XML:
Код:

<MAIN>
<PARENT>
        <TEXT>Title 1</TEXT>
</PARENT>
<PARENT>
        <TEXT>Title 2</TEXT>
        <SUB>
            <TEXT>Title 2.1</TEXT>
        </SUB>
        <SUB>
            <TEXT>Title 2.2</TEXT>
            <SUB>
                <TEXT>Title 2.2.1</TEXT>
            </SUB>
            <SUB>
                <TEXT>Title 2.2.2</TEXT>
            </SUB>
        </SUB>
        <SUB>
            <TEXT>Title 2.3</TEXT>
        </SUB>
</PARENT>
<PARENT>
        <TEXT>Title 3</TEXT>
</PARENT>
<PARENT>
        <TEXT>Title 4</TEXT>
</PARENT>
<PARENT>
        <TEXT>Title 5</TEXT>
        <SUB>
            <TEXT>Title 5.1</TEXT>
            <SUB>
                <TEXT>Title 5.1.1</TEXT>
            </SUB>
        </SUB>
        <SUB>
            <TEXT>Title 5.2</TEXT>
        </SUB>
</PARENT>
<PARENT>
        <TEXT>Title 6</TEXT>
</PARENT>
</MAIN>

КОД ПРОГРАММЫ:
Код:

function readXMLMenu() {
        var currentNode = XMLmenu.firstChild;
        var depth:Number = -1; //-1 для того, чтобы главный текстовый нод был с глубиной 1 (иначе 3)
        recursiv(depth, currentNode);
        function recursiv(depth, currentNode) {
                var i = 0;
                while (currentNode.childNodes[i]) {
                        if (currentNode.childNodes[i].nodeType == 3) {  //если нод текстовый, то считать его значение
                                var option = new Object();
                                option.depth = depth;
                                option.name = currentNode.childNodes[i].nodeValue;
                                menu.push(option);
                        }
                        recursiv(depth+1, currentNode.childNodes[i]);
                        i++;
                }
        }
        k = 0;
        while (menu[k]) {
                for (var prop in menu[k]) {
                        trace("myObject."+prop+" = "+menu[k][prop]);
                }
                k++;
                trace("________________________________");
        }
}


menu = new Array();
XMLmenu = new XML();
XMLmenu.ignoreWhite = true;
XMLmenu.onLoad = readXMLMenu;
XMLmenu.load("menuXML.xml");


В результате получаем линейный массив:
Код:

myObject.name = Title 1
myObject.depth = 1
________________________________
myObject.name = Title 2
myObject.depth = 1
________________________________
myObject.name = Title 2.1
myObject.depth = 2
________________________________
myObject.name = Title 2.2
myObject.depth = 2
________________________________
myObject.name = Title 2.2.1
myObject.depth = 3
________________________________
myObject.name = Title 2.2.2
myObject.depth = 3
________________________________
myObject.name = Title 2.3
myObject.depth = 2
________________________________
myObject.name = Title 3
myObject.depth = 1
________________________________
myObject.name = Title 4
myObject.depth = 1
________________________________
myObject.name = Title 5
myObject.depth = 1
________________________________
myObject.name = Title 5.1
myObject.depth = 2
________________________________
myObject.name = Title 5.1.1
myObject.depth = 3
________________________________
myObject.name = Title 5.2
myObject.depth = 2
________________________________
myObject.name = Title 6
myObject.depth = 1
________________________________


Хотелось бы услышать комментарии гуру по поводу этого решения (если они есть)...

wvxvw 23.11.2007 15:26

Честно... а зачем тогда грузить ХМЛ? Как по мне - количество избыточного кода >50%... Проще уже лоадварзом передать такую нехитрую инфу. Кроме того... если обязательно грузить именно ХМЛ, то я бы попробовал переназначить onData, а не onLoad - все быстрее было бы =)

Ведьмак 23.11.2007 17:08

Я, наверное, чего то не знаю.. лоадВарз хавает строку параметров да? Зачем дерево с неограниченной вложенностью загонять в строку параметров, когда есть XML? в придачу могу еще появиться аргументы у нодов...

чем onData лучше onLoad?

telit 23.11.2007 17:27

Код:

x = new XML ()
x.ignoreWhite = 1 // this is essential!
x.load ('YourXml.xml')
x.onLoad = function ()
{
        x_x = this.makeObj();
}

используй тот парсер который я выше постил! Он самый быстый и подходит для любой XML!!!

wvxvw 23.11.2007 17:28

хм... тебе ведь в итоге нужно получить одномерный массив, ХМЛ структура гораздо более сложная чем массив - вопрос, зачем ее тогда использовать на 10%, если то же самое можно реализовать гораздо проще?
онДата - событие возникающее сразу после того, как строка содержащая в себе неотпарсеный ХМЛ полностью загрузится в флешку.
онЛоад - соотвественно, по завершению парсинга.
Т.е. если ты не используешь большую часть возможностей ХМЛя - зачем тогда его вообще парсить, да еще и 2 раза? Просто, возьми строку, да и выйми из нее нужную информацию - построй объект, как тебе нравится. Ща попробую накатать что-нибудь для примера

udaaff 23.11.2007 21:43

Еще один линк до кучи http://www.flasher.ru/forum/showthread.php?t=103150 =)

wvxvw 24.11.2007 01:46

Код:

var _xml:XML = new XML();
_xml.onData = function(s:String):Void {
        while(s.indexOf("\r")>-1){
                s = s.split("\r").join("");
        }
        while(s.indexOf("\t")>-1){
                s = s.split("\t").join("");
        }
        while(s.indexOf("\n")>-1){
                s = s.split("\n").join("");
        }
        while(s.indexOf("> ")>-1){
                s = s.split("> ").join(">");
        }
        s = s.substring(s.length-1,1);
        var o_arr:Array = s.split("><");
        trace(o_arr);
        var r_arr:Array = [];
        var dp:Number = -1;
        for(var i:Number=0;i<o_arr.length;i++){
                if(o_arr[i].indexOf("/")<0){
                        dp++;
                } else {
                        dp--;
                }
                if(o_arr[i].indexOf(">")>-1){
                        dp++;
                        r_arr.push({name:o_arr[i].substring(o_arr[i].indexOf(">")+1,o_arr[i].indexOf("<")),depth:dp});
                }
        }
        for(var q:Number=0;q<r_arr.length;q++){
                trace("Name: "+r_arr[q].name);
                trace("Depth: "+r_arr[q].depth);
                trace("============");
        }
}
_xml.load("test.xml");

Вот, попробуй со своим ХМЛем %)

Double 24.11.2007 15:24

начинать надо с оптимизации xml. те же данные:
Код:

<MAIN>
<PARENT TEXT="Title 1" />
<PARENT TEXT="Title 2">
        <SUB TEXT="Title 2.1" />
        <SUB TEXT="Title 2.2">
            <SUB TEXT="Title 2.2.1" />
            <SUB TEXT="Title 2.2.2" />
        </SUB>
        <SUB TEXT="Title 2.3" />
</PARENT>
<PARENT TEXT="Title 3" />
<PARENT TEXT="Title 4" />
<PARENT TEXT="Title 5">
        <SUB TEXT="Title 5.1">
            <SUB TEXT="Title 5.1.1" />
        </SUB>
        <SUB TEXT="Title 5.2" />
</PARENT>
<PARENT TEXT="Title 6" />
</MAIN>

а чем поможет линейный массив при создании древовидного меню?.. не вижу смысл приведения дерева в линейную структуру, чтобы на её основе потом пытаться восстановить дерево...

udaaff 24.11.2007 16:08

Double, на мой взгляд не надо ничего оптимизировать в данном случае. Так как задача, я так понял, создать объект на основе xml, а объект лучше описать тем сопобом, который у Ведьмака.
На счет массива: смысл перегона xml в массив отсутствует.

Double 24.11.2007 16:10

так xml - и есть объект.

udaaff 24.11.2007 16:14

Я немного не отом.. посмоти мой линк несколькими постами выше.

Double 24.11.2007 18:50

всё равно я не понимаю. а чем удобнее этот объект? что принципиально поменялось? обращаться к конкретному значению, как portfolio.websites.трам-пам-пам? а если завтра в xml появятся работы webradio? fla переписывать? смысл-то какой? нет, я правда не понимаю, чем xml плох...

udaaff 24.11.2007 21:59

Зачем нужно xml в объект перегонять и наоборот:
1. -- проще обратиться к какому то свойству
-- проще его изменить
Т.е., если тебе просто надо построить менюшку, на основе xml, преобразовывать xml в объект не надо, но если нужно обращаться к разным свойствам в разное время, и если их куча, то удобнее обращаться по именам.
2. можно сохранять сложные типы данных (в виде xml) и считывать их потом, тот же объект (если юзаешь mdm zinc, то без xml или sharedobject, тебе не обойтись, если захочешь объект сохранить, к примеру, теже настройки программы)

iNils 24.11.2007 22:19

Цитата:

Сообщение от udaaff
но если нужно обращаться к разным свойствам в разное время, и если их куча, то удобнее обращаться по именам.

У xml есть возможность обращения к любому ноду по его уникальному id.

kruasan 24.11.2007 23:17

Вспомнилась тема:
http://www.flasher.ru/forum/showthre...E5%E3%EE%ED%E8

Double 25.11.2007 20:36

блин, ну xml - это удобный способ описания древовидной структуры. если структура данных есть дерево, то кроме xml уже ничего не нужно. если сруктура данных не есть дерево, тогда и про xml нет смысла вспоминать.

Ведьмак 29.11.2007 15:16

спасибо всем )

Dove 01.08.2008 00:23

Есть еще вариантик отображения дерева XML
Код:

var menuXML:XML;
var menuItems:Array = new Array();
menuXML = new XML();
menuXML.ignoreWhite = true;
menuXML.onLoad = function() {
        menuIsLoaded(menuXML.firstChild,"|");
};

menuXML.load("data/menu.xml");

function menuIsLoaded(thMenuXML, idnt) {
        if (thMenuXML.hasChildNodes()) {
                idnt += "|\t";
                for (item in thMenuXML.childNodes) {
                        if (thMenuXML.childNodes[item].nodeValue !== null) {
                                trace(idnt+thMenuXML.childNodes[item].nodeValue);
                        }
                        menuIsLoaded(thMenuXML.childNodes[item],idnt);

                }
        }
}



Часовой пояс GMT +4, время: 11:17.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.