PDA

Просмотр полной версии : Получить данные из нескольких XML


KiL33
15.02.2009, 11:45
В компонент DataGrid подгружается некоторое кол-во xml.
Проблема в получении данных возникает в том случае, если xml грузятся не по порядку.
telumentFiles = ["Find1.xml","Find3.xml"]Можно как-то исправить?

Fatality
15.02.2009, 13:51
А нельзя ли подробнее, в чем собственно проблема.

Котяра
15.02.2009, 14:01
Отслеживай очередность загрузки и вызывай следующую после получения предыдущей.
У меня есть класс для загрузки. правда в нем еще присутствуют проверки на специальные ошибки и правомерность вызова ( возврат сервером в качестве атрибута xml done="true/false" и error="номер ошибки"
/**
* Класс загрузчик XML -
* позволяет ставить загрузки в очередь и назначать обработчики событий загрузки
* @author k0t0vich (c) 2008
*/

//import mx.data.encoders.Num;
import mx.utils.Delegate;

class XMLLoader extends Object
{
// Флаг имеется ли соединение к сокет серверу
private var _isSocketConnected:Boolean;
// максимальное число повторных вызовов при обрыве связи

public var maxCallingCount:Number = 5;
private var _log:String = '';


// Флаг загрузился ли предыдущий вызов
private var prevLoaded:Boolean = true;

// очередь вызовов
private var dataStack:Array;



//текущий объект вызова
private var dataObject:Object;
//текущий объект Асинхронного вызова
//private var dataAsincObject:Object;

//var socket:XMLSocket;
var socket:Object;

public function get isSocketConnected():Boolean
{
return _isSocketConnected;
}


public function get log():String
{
return _log;
}

// конструктор
public function XMLLoader()
{

trace ("XMLLoader: constructor+++");
dataStack = new Array();
dataStack = [];
dataObject = new Object();


}


// ТаймСтамп
public function timeStamp():Number
{
var today:Date = new Date();
return today.valueOf();
}

// Очистить лог
public function clearLog()
{
allSize = 0;
_log = '';
}

var allSize:Number = 0;
private function addToLog(data:Object)
{
data.onLoadTime = timeStamp();
var tmp_log:String;
var byteSize = data._xml.getBytesTotal();
allSize += byteSize;
tmp_log= "----------------"+allSize+"-----------------------------------------------\r"
if(data.asinc== true)tmp_log += "Асинхронный вызов\r";
tmp_log += 'URL:' + data.url+"\r";
tmp_log += 'Поставлен в очередь:' + data.startTime+"\r";
tmp_log += 'Ожидание в очереди, мс:' + (data.loadTime-data.startTime)+"\r";
tmp_log += 'Время загрузки, мс:' + (data.onLoadTime-data.loadTime)+"\r";
tmp_log += 'Размер, байт:' +byteSize +"\r";
tmp_log += 'Количество вызовов:' + data.counter+"\r\r";
tmp_log += 'XML:\r' + data._xml+"\r";

if (data._xml.firstChild.attributes.error!=undefined)
{
tmp_log += "Ошибка: "+_root.lang_atr["errmsg"+data._xml.firstChild.attributes.error]+'\r';
}
trace(tmp_log);
_log = tmp_log +_log;
}


// Функция помещения скрипта в очередь
// url:String - адрес
// onLoadFunction - функция для обработки полученной XML( в качестве аргумента должен быть тип XML)
// http:Boolean - вызов строго через http запрос, по умолчанию false - вызов по сокет соединению
public function load(url:String,onLoadFunction:Function, http:Boolean,local:Boolean) :Boolean
{
//loadAsinc(url, onLoadFunction);
//return true;

trace ("XMLLoader: load"+url);
// вызов строго через htpp запрос по умолчанию
//TODO: сделать false
http = (http == undefined)?true:http;

local = (local == undefined)?false:local;

// установка значений объекта вызова
var dataObject:Object = new Object();
dataObject.url = url;
dataObject.local = local;
dataObject.onLoadFunction = onLoadFunction;
dataObject.http = http;
dataObject.startTime = timeStamp();

// если пустая очередь - добавить вызов в очередь и запустить
if (dataStack.length == 0 && prevLoaded)
{
dataStack.push(dataObject);
loadNextData();
}
// иначе только добавить в очередь
else
{
dataStack.push(dataObject);
}

return true;

}
// загрузить следующий по очереди

var my_timedProcess:Number;

private function loadNextData():Boolean
{
if (dataStack.length == 0 )
{
return false;
}
else if (prevLoaded)
{
prevLoaded = false;
//основной вызов
dataObject = new Object();
dataObject = dataStack.shift();
// счетчик вызовов при обрыве связи
dataObject.counter = 0;

if (_isSocketConnected && !dataObject.http)
{
//TODO: socket
}
else
{
// запрос XML по http
loadDataObjectXML();

}

}
return true;
}


private function loadDataObjectXML()
{
dataObject.counter++;
dataObject._xml = new XML();
dataObject._xml.ignoreWhite = true;
dataObject.loadTime = timeStamp();
if (!dataObject.local)
dataObject.url += "&uncash" + timeStamp();
dataObject._xml.load(dataObject.url);
dataObject._xml.onLoad = Delegate.create(this, onLoadXML);
}

function get_unchase_data()
{
return getTimer();
}


private function onLoadXML(success)
{
if (success)
{
if (dataObject._xml.firstChild.attributes.done == "true")
{
// вызов функции обработчика
addToLog(dataObject);
dataObject.onLoadFunction(dataObject._xml);
// вызов следующего в очереди
prevLoaded = true;
loadNextData();
}
else
{
// обработчик стандартных ошибок.
addToLog(dataObject, true);
_root.dealWithErr(dataObject._xml);
prevLoaded = true;
loadNextData();
}
}
else
{ // обработчик ошибок - соединение не установлено
// повторная загрузка XML
if (dataObject.counter < maxCallingCount)
{
loadDataObjectXML();
}
else
{
// ошибка - соединение не установлено
dataObject._xml = new XML("<data error='101'/>");
addToLog(dataObject);
_root.dealWithErr(dataObject._xml);
prevLoaded = true;
loadNextData();
}
}

}

// Функция Ассинхронного вызова
// url:String - адрес
// onLoadFunction - функция для обработки полученной XML( в качестве аргумента должен быть тип XML)
// http:Boolean - вызов строго через http запрос, по умолчанию false - вызов по сокет соединению
public function loadAsinc(url:String,onLoadFunction:Function, http:Boolean,local:Boolean)
{
// вызов строго через htpp запрос по умолчанию
//TODO: сделать false
http = (http == undefined)?true:http;

local = (local == undefined)?false:local;

// установка значений объекта асинхронного вызова
var dataAsincObject= new Object();
dataAsincObject.url = url;
dataAsincObject.onLoadFunction = onLoadFunction;
dataAsincObject.http = http;
dataAsincObject.local = local;
dataAsincObject.startTime = timeStamp();
dataAsincObject.counter = 0;
dataAsincObject.asinc= true;

loadDataAsincObjectXML(dataAsincObject);

}


private function loadDataAsincObjectXML(dataAsincObject)
{ dataAsincObject.counter++;
dataAsincObject._xml = new XML();
dataAsincObject._xml.ignoreWhite = true;
dataAsincObject.loadTime = timeStamp();
if (!dataAsincObject.local)
dataAsincObject.url += "&uncashing" + timeStamp();
dataAsincObject._xml.load(dataAsincObject.url);
dataAsincObject._xml.onLoad = Delegate.create(this, function(success) {onLoadAsincXML(dataAsincObject,success)});
}



private function onLoadAsincXML(dataAsincObject,success)
{
if (success)
{
if (dataAsincObject._xml.firstChild.attributes.done == "true")
{
// вызов функции обработчика
addToLog(dataAsincObject);
dataAsincObject.onLoadFunction(dataAsincObject._xml);
}
else
{
// обработчик стандартных ошибок.
addToLog(dataAsincObject);
_root.dealWithErr(dataAsincObject._xml);

}
}
else
{
// обработчик ошибок - соединение не установлено
// повторная загрузка XML
if (dataAsincObject.counter < maxCallingCount)
{
dataAsincObject.counter++;
loadDataAsincObjectXML(dataAsincObject);
}
else
{
// ошибка - соединение не установлено
dataAsincObject._xml = new XML("<data error='101'/>");
addToLog(dataAsincObject);
_root.dealWithErr(dataAsincObject._xml);
}
}

}

}

Т.е. класс используется так:
xmlLoader = newXMLLoader();
xmlLoader.load(url,funk1);

KiL33
15.02.2009, 15:25
Котяра, спасибо за класс, но не кажется ли, что это слишком жирно для моей проблемки)
А нельзя ли подробнее, в чем собственно проблема.
telumentFiles = ["Find1.xml", "Find2.xml", "Find3.xml"];
Файла Find2.xml может и не быть, но если его нет, то с последующих xml (Find3…и т.д) не могу получить данные.
Нуу в исходнике косяк можно сразу увидеть

Fox M. Lurde
15.02.2009, 16:06
Попробуй предварительно проверять на существование файлов, и обращайся только к тем, которые есть в наличии - по идее, должно помочь.

Котяра
15.02.2009, 17:41
Попробуй предварительно проверять на существование файлов, и обращайся только к тем, которые есть в наличии - по идее, должно помочь.
А что это даст? и как в ас2 проверить существовани е файла? можно только по онЛоду принять параметр фалс.

2Автор: поместил бы код в топик, а то качать лень, да и не всегда есть флэшИДЕ.
telumentFiles = ["Find1.xml", "Find2.xml", "Find3.xml"];
var xmlArr:Array=[];
for (var i:Number = 0; i<telumentFiles.length; i++) {
var myXML:XML = new XML();
xmlArr.push(myXML);
myXML.ignoreWhite = true;
aName = telumentFiles[i];
myXML.load(aName);
myXML.onLoad = function(success) {
// ВОТ ЗДЕСЬ НЕ ОБЯЗАТЕЛЬНО ПРОВЕРЯТЬ НА ЗАГРУЖЕННОСТЬ,
// ЕСЛИ НАДО ПРОДОЛЖИТЬ - ПРОДОЛЖАЙ БЕЗ ПРОВЕРКИ
// if (success)
{
myXML_first = this.firstChild;
populateTable(myXML_first);
}
};
}
function populateTable(str_xml:Object) {
for (n=0; n<str_xml.childNodes.length; n++) {
Razdel_1 = str_xml.childNodes[n].firstChild.firstChild.nodeValue;
Razdel_2 = str_xml.childNodes[n].firstChild.nextSibling.firstChild.nodeValue;
Razdel_3 = str_xml.childNodes[n].firstChild.nextSibling.nextSibling.firstChild.nodeValue;
Razdel_4 = str_xml.childNodes[n].firstChild.nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
myTable.addItem({Раздел_1:Razdel_1, Раздел_2:Razdel_2, Раздел_3:Razdel_3, Раздел_4:Razdel_4});
}
myTable.getColumnAt(0).width = 100;
myTable.getColumnAt(1).width = 100;
myTable.getColumnAt(2).width = 100;
myTable.getColumnAt(3).width = 200;
}
//////////////////////////////////////////
function showDetails(myXML:Object):Void {
for (n=0; n<myXML.childNodes.length; n++) {
result_text.text = myXML.childNodes[n].firstChild.firstChild.nodeValue
}
}
////////////////////////////////////////////////Действие при клике мышью
function change(eventObject) {

showDetails(xmlArr[myTable.selectedIndex].firstChild);

};
myTable.addEventListener("change", change);
СМ. ПЕРВЫЙ КОМЕНТ В КОДЕ.
Я правда так и не понял проблемы.. в примере не грузится xml2, и что? третья грузится.. Что надо?
Выводить их по порядку? Что именно не работает?

KiL33
15.02.2009, 19:17
Проблема не в подгрузке xml-ок, а в выводе информации.
Что именно не работает?
21551
:)
Данные из Find1.xml взять получается кликнув мышью по кнопке в компоненте, данные из Find3.xml не получается взять, так как Find2.xml может отсутствовать.

Котяра
15.02.2009, 20:49
Проблема не в подгрузке xml-ок, а в выводе информации.
А причем тут недоступные XML? Проблема то не в этом, а в populateTable
есть xml2 или нет - одинаково..
может проблема в 5 строке.
xmlArr.push(myXML);
здесь ты добавляешь еще не загруженную xml. Добавляй ее в xml.onLoad

KiL33
16.02.2009, 11:14
может проблема в 5 строке... Добавляй ее в xml.onLoad
не..в таком случае получается на оборот из xml3 инфа берется из xml1 нет.
А причем тут недоступные XML?
ну да в принципе не причём может не много вопрос не правильно поставил, более того если в функции populateTable исправить число в цикле с 0 на -1
for (n=-1; n<str_xml.childNodes.length; n++) {
то все работает как надо, но тогда появляются лишние совсем не нужные Итемы.