PDA

Просмотр полной версии : Как из функции вытащить ссылку на XMLNode


mrspb
23.12.2006, 08:44
function searchNode (myXML, nN:String){
//ищет нод по имени nN в myXML
for (var i = 0; i<myXML.childNodes.length; i++) {
if (String (myXML.childNodes[i].nodeName) != nN) {
searchNode (myXML.childNodes[i], nN);
} else {
ccc = myXML.childNodes[i];
return myXML.childNodes[i];
}
}
}
хочу юзать так:
bbb = searchNode (des_xml, 'atp');
ссс - получается нормальная юзабельная ссылка, bbb получется undefined
//в общем сабж

CorC
23.12.2006, 10:13
1. в чем может быть косяк:
function searchNode (myXML, nN:String){ тип функции не указан хотя return есть
2. можно попробовать ccc = myXML.childNodes[i].toString()
3. может вы неуспеваете дождаться окончания загрузки ХМЛ а уже с ним что-то делаете...

iNils
23.12.2006, 10:29
1. У меня это работает (xml описан в скрипте)
2. Зачем в строке if (String (myXML.childNodes[i].nodeName)... стоит приведение имени нода к String, когда имя нода и так String?

И наконец главный вопрос:
3. Что будете делать, если у вас несколько нодов с именем 'atp'?

Вот функция который обходит весь xml и возвращает массив нодов с заданным именем.
//// ноды с именем A имеют номера id: 1,4,6,7
//// ноды с именем B имеют номера id: 2,3,5,8
var xml:XML = new XML ("<nodeA id='1'><nodeB id='2'><nodeB id='3'><nodeA id='4'></nodeA></nodeB><nodeB id='5'></nodeB><nodeA id='6'><nodeA id='7'></nodeA></nodeA></nodeB><nodeB id='8'></nodeB></nodeA>");
xml.ignoreWhite = true;

function searchNode (xml:XML, name:String, array:Array):Array {
if (arguments.length < 3) {
var array:Array = new Array ();
}
if (xml.nodeName == name) {
array.push (xml);
}
if (xml.hasChildNodes () || xml.childNodes.length != 0) {
var i:Number = 0;
while (xml.childNodes[i]) {
searchNode (xml.childNodes[i++], name, array);
}
}
return array;
}

var arrayNodeA:Array = searchNode (xml, 'nodeA');
var arrayNodeB:Array = searchNode (xml, 'nodeB');
for (var i:Number = 0; i < arrayNodeA.length; i++) {
trace (arrayNodeA[i].attributes.id);
}
trace ("");
for (var i:Number = 0; i < arrayNodeB.length; i++) {
trace (arrayNodeB[i].attributes.id);
}

mrspb
23.12.2006, 11:12
CorC
с типом тож не хочет...
iNils
1. примерно такая же функция есть и у меня. но надо "лёгкую" функцию тк вызываться она будет часто и на слабой тачке
2. это для перестраховки.
3. xml-ка самопальная, имена в ней уникальные.
тоже запихаю ссылку в массив и его возвращу, пасибо :)

iNils
23.12.2006, 11:27
Тогда поиск вообще не нужен. Можно по уникальному id обращаться.
var xml:XML = new XML ("<nodeA id='1'><nodeB id='2'><nodeB id='w'><nodeA id='4'></nodeA></nodeB><nodeB id='5'></nodeB><nodeA id='6'><nodeA id='7'></nodeA></nodeA></nodeB><nodeB id='8'></nodeB></nodeA>");
xml.ignoreWhite = true;
trace (xml['idMap']['4']);
trace (xml['idMap']['w']);

etc
23.12.2006, 12:26
А зачем idMap в скобках? :)

mrspb
23.12.2006, 12:27
весь код
des_xml = new XML ();
des_xml.ignoreWhite = true;
des_xml.load('des.des');
des_xml.onLoad = function (){
trace (true);
}
kkk = [];
this.onMouseDown = function () {
kkk = searchNode (des_xml, 'atp');
}

function searchNode (myXML:XMLNode, nN:String):Array{
//ищет нод по имени nN в myXML
for (var i = 0; i<myXML.childNodes.length; i++) {
if (String (myXML.childNodes[i].nodeName) != nN) {
searchNode (myXML.childNodes[i], nN);
} else if (String (myXML.childNodes[i].nodeName) == nN) {
trace ('i find node ' + nN);
var tmp_arr = [myXML.childNodes[i]];
return tmp_arr;
}
}
}
я не понимю почему оно не работает? тут нечему не работать! kkk получается undefined, хотя в массиве был элемент...
XML'ka такая
<doct>
<atp><![cdata[A<des>АЦП]]></atp>
<ist><![cdata[AV<des>Источник тока]]></ist>
<vm_area><![cdata[V<des>вольтметр]]></vm_area>
</doct>

iNils
23.12.2006, 12:50
А зачем idMap в скобках? :)Так и знал, что кто-то на это внимание обратит :)
Я не пользовался idMap с времен когда сидел на mx (вернее там и писать idMap не нужно было). И когда сейчас стал набирать idMap, то флеш стал ругаться.
**Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 5: There is no property with the name 'idMap'.
trace (xml.idMap['4']);

Total ActionScript Errors: 1 Reported Errors: 1Заглянул в XMLNode.as, а там отсутствует var idMap:Object. Пришлось в скобках писать.

etc
23.12.2006, 12:59
Мммм, это в каком Flash такая заморочка?

iNils
23.12.2006, 13:06
Мммм, это в каком Flash такая заморочка?Flash Professional 8.

etc
23.12.2006, 13:08
Очень странно, если у тебя не кастомный класс, который расширяет XML, то всё должно работать. Во всяком случае, у меня без всяких правок работает:
xml = new XML('<node id="3">');
trace(xml.idMap['3']);

idMap в intrinsic не прописан.

etc
23.12.2006, 13:11
А, всё ясно. Такой косяк возникает, если использовать var xml:XML = …
Лучше не править intrinsic и не пользовать скобки — лучшим решением будет написание кастомного класса, расширяющий XML. Я пользую исключительно свой AbstractXML:

import mx.events.EventDispatcher;
/**
* @author Denis Kolyako
*/
class ru.etcs.data.AbstractXML extends XML {

private var __xml_url:String;

public var event:String = 'onXMLLoad';
public var errorEvent:String = 'onXMLLoadError';
public var idMap:Object;

public var dispatchEvent:Function;
public var addEventListener:Function;
public var removeEventListener:Function;

public function AbstractXML(xml_url:String) {
super("");
this.ignoreWhite = true;
EventDispatcher.initialize(this);
this.__xml_url = xml_url;
this.load(this.__xml_url);
}

private function onLoad(ok:Boolean):Void {
if (!ok || !this.loaded || this.status || this.getBytesTotal()<30) {
trace('XML loaded: '+this.loaded+', valid: '+this.status);
this.dispatchEvent({type:this.errorEvent});
return;
}
this.prepareData();
this.dispatchEvent({type:this.event});
}

private function prepareData():Void {
// For override
}

}
Может, кому-нибудь пригодится…

iNils
23.12.2006, 13:18
Это все хорошо, но не будешь же ты каждый раз здесь отвечая говорить о том, что нужно еще и класс скачать.
Если ответ в пару строк, то скобки не так страшны, по сути ты ничего не нарушаешь, ты же не виноват, что в intrinsic забыли написать то, что там должно быть.

etc
23.12.2006, 14:49
Не, просто при передаче проекта кому-либо лучше заюзать класс какой-нибудь, я про это.

mrspb
23.12.2006, 20:22
des_xml = new XML ('<doct><atp><![cdata[A<des>АЦП]]></atp><ist><![cdata[AV<des>Источник тока]]></ist><vm_area><![cdata[V<des>вольтметр]]></vm_area></doct>');
des_xml.ignoreWhite = true;
//des_xml.load('des.des');
des_xml.onLoad = function (){
trace (true);
}
kkk = new Array();
this.onMouseDown = function () {
kkk = searchNode (des_xml, 'ist');
trace ('***********************************');
trace (kkk)
//clearNode(ccc);
}

function searchNode (myXML:XML, nN:String):Array{
//ищет нод по имени nN в myXML
for (var i = 0; i<myXML.childNodes.length; i++) {
if (myXML.childNodes[i].nodeName == nN) {
//trace ('i find node ' + nN);
return [myXML.childNodes[i]];
} else if (myXML.childNodes[i].nodeName != nN) {
searchNode (myXML.childNodes[i], nN);
}
}
}
пожалста, провеьте, что при щелчке выводит?

etc
24.12.2006, 00:49
Ну, вообще, судя по коду, должно быть undefined :)

mrspb
24.12.2006, 05:00
во! есть на свете люди! почему? вроде возвращаю массив и тут же его присваиваю kkk?

etc
24.12.2006, 13:04
Ну представь просто, как работает твой код. Если условие не выполняется, то происходит запуск этой функции второй раз и т.д. Так вот этот return, что был в самом начале уже никогда не выполнится из-за условия. А все последующие итерации, даже если нужный нод будет найден, будут выполнены в холостую — все возвраты уйдут в никуда, потому что ты его никуда не сохраняешь.

По-хорошему, это должно быть так:

des_xml = new XML('<doct><atp><![cdata[A<des>АЦП]]></atp><ist><![cdata[AV<des>Источник тока]]></ist><vm_area><![cdata[V<des>вольтметр]]></vm_area></doct>');
des_xml.ignoreWhite = true;
//des_xml.load('des.des');
des_xml.onLoad = function() {
trace(true);
};
kkk = new Array();
this.onMouseDown = function() {
kkk = searchNode(des_xml, 'ist');
trace('***********************************');
trace(kkk);
//clearNode(ccc);
};
function searchNode(myXML:XMLNode, nN:String, arr:Array):Array {
if (arr == undefined) { // если в функцию не передали ссылку на arr
var arr:Array = new Array();
}
if (arr.length) { // уже нашли, значит можно уже ничего не делать
return;
}
var nodes:Array = myXML.childNodes;
for (var i = 0; i<nodes.length; i++) {
var node:XMLNode = nodes[i];
if (node.nodeName == nN) {
arr.push(node);
} else {
searchNode(node, nN, arr);
}
}
return arr;
}

mrspb
25.12.2006, 06:36
__etc
Огромное спасибо!