PDA

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


Ventur
10.09.2007, 19:25
Здравствуйте. Столкнулся с проблемой загрузки больших XML-файлов (порядка 1мб и выше). Загрузка с локальной директории.
Как и следовало ожидать, флеш по истечении 15 секунд выдает модальное окно с запросом на разрешение продолжения выполнения скрипта. Решил разбить xml-файл на несколько (скажем, по 20 строк каждый). Гружу данные через loadVars, каждую новую партию присоединяю к строке (как вариант - concat), по завершении загрузки паршу в xml. В итоге, доступа к определенному узлу, атрибуту... отсутствует, ввиду, как я понял, неверной конечной структуры XML.
Ранее, при загрузке через loadVars xml-данных использовал метод sendAndLoad и ресивером делал XML переменную, но, та м не было разбиения на строки.

Вот примерный код, который использую сейчас.

var xml:String = " ";
var current:Number = 0;
function loadData(path:String) {
var my_lv:LoadVars = new LoadVars();
clearInterval(interval);
my_lv.onLoad = function(success:Boolean) {
trace(current+"-------------------");
if (success) {
current++;
xml+=this.toString();
if (current<=2) {
interval = setInterval(loadData, 2000, "multixml/"+current+".xml");
} else {
var level_xml:XML = new XML();
level_xml.ignoreWhite = true;
level_xml.parseXML(xml);
trace(level_xml);
}
} else {
trace("Error loading/parsing LoadVars.");
}
};
my_lv.load(path);
}
var interval:Number = setInterval(loadData, 2000, "multixml/0.xml");

Буду рад выслушать ваши замечания и предложения по поводу нормального преобразования строки в xml.
Спасибо

Kikasso
10.09.2007, 23:28
А почему сразу xml не загрузить?

udaaff
10.09.2007, 23:28
А что толку грузить частями? Все равно время общее одно и тоже будет. Провел эксперимент ради интереса: загрузил файл 13 мб, все замечательно загрузилось.

to Kikasso: по всей видимости у Ventur'а он грузится слишком долго.

Ventur
11.09.2007, 02:40
Нет, когда одна сессия больше 15 сек - выскакивает Abort....
Потому и гружу частями. В итоге прерывание, смотри интервал в коде

Kikasso
11.09.2007, 03:10
Не разу не сталкивался, но я таких файлов и не грузил. Можно попробовать что-то такое:
var mainXML = new XML('<xml/>');
var part = 1;
var path = 'file.php'; //ну или кто там
var tempXML = new XML();
tempXML.ignoreWhite = true;
tempXML.onLoad = function(){
mainXML.firstChild.appendChild(this.firstChild);
}
tempXML.load( path + '?part='+part );
Вообще это странно, может у вас что в коде зацикливает?
upd^ код поправил

Ventur
11.09.2007, 09:47
Нет, не зацикливает, xml большого размера, потому время загрузки/обработки составляет больше 15 секунд. Даже если просто пустой скрипт загрузки.
Видимо, строки в длину слишком большие. Для теста я могу вам выслать свой xml и вы увидите.
XML имеет структуру, схожую с SVG (векторный формат данных).
Проблема в загрузке файлов больше 1мб, а не а парсинге и прочей обработке.

Kikasso
11.09.2007, 12:00
Я все еще не понимаю.
var myX:XML = new XML();
var intervalID:Number;
myX.onData = function(src){
txt.text ='ok';
clearInterval(intervalID);
}
function checkProgress(xmlObj:XML):Void {
var bytesLoaded:Number = xmlObj.getBytesLoaded();
var bytesTotal:Number = xmlObj.getBytesTotal() || 10000000;
var percentLoaded:Number = Math.floor(((bytesLoaded || .01) / bytesTotal ) * 100);
txt.text = "percent loaded: " + percentLoaded;
}
myX.load('Landing.mp3');
intervalID = setInterval(checkProgress, 100, myX);
mp3 - 3 метра с небольшим, гружу с модемной скоростью через webSpeedSimulator, грузится около 5 минут, в конце говорит "ок".
Откуда эта история с 15 секундами?

гружу mp3, потому что искать большой текстовик лень. Парсить я его не собираюсь )) А на этапе загрузки флешу не важно что грузить.

Ventur
11.09.2007, 20:39
:), вы еще клип грузите, ан е mp3.
С xml все иначе.
В общем, решение проблемы - unescape();
Спасибо за участие

Верный код типа этого:



var xml:String = "";
var current:Number = 0;
function loadData(path:String) {
var my_lv:LoadVars = new LoadVars();
clearInterval(interval);
my_lv.onLoad = function(success:Boolean) {
if (success) {
current++;
xml+=this.toString();
if (current<=2) {
interval = setInterval(loadData, 2000, "multixml/"+current+".xml");
} else {
var level_xml:XML = new XML();
level_xml.ignoreWhite = true;
level_xml.parseXML(unescape(xml));
trace(level_xml);
}
} else {
trace("Error loading/parsing LoadVars.");
}
};
my_lv.load(path);
}
var interval:Number = setInterval(loadData, 2000, "multixml/0.xml");

Kikasso
11.09.2007, 22:13
Что грузить, без разницы. Вот нашел какой-то текстовик на 4 мега, обозвал его "test.xml" и гружу этим же кодом, только onData поменял. Время загрузки 323 секунды.
myX.onData = function(src){
txt.text = src;
clearInterval(intervalID);
}
myX.load('test.xml');
Все нормально грузится.
Откуда вы взяли 15 секунд?

Molecula
11.09.2007, 22:16
Опять эти 15 секунд, я про них уже где-то слышал!

Kikasso
11.09.2007, 22:23
15 секунд - ограничение на выполнение кода. Вот сейчас выскочит:
while( true ){}

Molecula
11.09.2007, 22:25
Ага! Тяжелые секунды процессора!

Ventur
11.09.2007, 23:05
http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_15512

...
Loading large amounts of data
If the application loading large amounts of data (for example, 1000 records returned from a query,) consider the delivery mechanism. Most applications cannot usefully display a set of 1000 records in one view. Instead, load and display data in small chunks. This may solve a variety of problems in the application: overall performance, usability, and as a side benefit it avoids triggering the timeout alert.

Note: The number 1000 in this example is an arbitrary number. The maximum number of records allowed before this alert box appears depends on the amount of data in the XML file, the connection speed, and the speed of the client machine.

Examples:
Macromedia DataGrid Component
It's difficult to work with many records at once in the DataGrid.Pull in small chunks of data, about as much as can be efficiently displayed and used at once, and you should have improved results. 100 records at once could suit the DataGrid better than 1000, for example.
Loading Large XML Files
Loading excessively large XML files can cause the script timeout error.

Kikasso
11.09.2007, 23:18
Проблема в загрузке файлов больше 1мб, а не а парсинге и прочей обработке.
Так вот проблема как раз в обработке.. Сорри. Попробуйте, правда,
appendChild (XMLNode.appendChild method)

Ventur
11.09.2007, 23:24
Нет. Проблема решена, я описал выше

Kikasso
12.09.2007, 00:40
Значит так, нашел я в хелпе xml на 4 метра, наблюдал то же самое - скрипт вылетает, то есть одним куском флеш такое не парсит. Тогда я разбил этот xml на куски строк по 50 -100 блоками CDATA, получил xml такого вида:
<?xml version="1.0" encoding="UTF-8"?>
<book title="Components Language Reference" directory="ComponentRef">
<![CDATA[<book>
... тут строк 50 ...
</book>]]>
<![CDATA[<book>
... тут строк 100 ...
</book>]]>
</book>
Всего около 1500 строк.
И написал такое:
var myX:XML = new XML();
myX.ignoreWhite = true;
var finX:XML = new XML('<xml/>');
var intervalID:Number;
var i = 1;

myX.onLoad = function (ok){
trace (ok + " " + this.status);
clearInterval(intervalID);
var node = this.firstChild.firstChild;
onEnterFrame = function () {
parseXMLPart(node);
};
};
function parseXMLPart(node){
trace (i++);
delete onEnterFrame;
txt.text = node.toString();
var tempX = new XML(node.nodeValue);
var currNode = tempX.firstChild.firstChild;
while(currNode !=null){
finX.firstChild.appendChild(currNode);
currNode = currNode.nextSibling;
}
delete currNode;
delete tempX;
node = node.nextSibling;
if (node != null) {
onEnterFrame = function (){
parseXMLPart(node);
};
}else{
delete myX;
trace(finX);
txt.text = finX.toString();
}
}
function checkProgress(xmlObj:XML):Void {
var bytesLoaded:Number = xmlObj.getBytesLoaded();
var bytesTotal:Number = xmlObj.getBytesTotal() || 10000000;
var percentLoaded:Number = Math.floor(((bytesLoaded || .01) / bytesTotal ) * 100);
txt.text = "percent loaded: " + percentLoaded;
}
myX.load('test.xml');
intervalID = setInterval(checkProgress, 100, myX);
И все отлично прощелкалось :victory:
Код конечно сыроват, расчитан на xml определенной структуры..

Встроенный debug не стоит делать с xml такого размера - флеш гарантировано вылетит. Только самописный.