Вход

Просмотр полной версии : Parse XML с неограниченной вложенностью


Ведьмак
22.11.2007, 16:58
Всем, доброго дня!

Есть 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
но если нужно обращаться к разным свойствам в разное время, и если их куча, то удобнее обращаться по именам.У xml есть возможность обращения к любому ноду по его уникальному id.

kruasan
24.11.2007, 23:17
Вспомнилась тема:
http://www.flasher.ru/forum/showthread.php?t=70447&highlight=%EF%E5%F0%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);

}
}
}