Ускорить обработку xml парсером

Рейтинг: 1Ответов: 2Опубликовано: 17.02.2015

Здравствуйте.

Есть такой код парсера:

<script>
$(document).ready(function () {
    $.ajax({
        type: "GET",
        url: "pg.xml",
        dataType: "xml",
        success: xmlParser
    });
});

var globaltext
var globalid
var globalploshad
function xmlParser(xml) {

    $('#load').fadeOut();
    $find = $(xml).find('grupa_proektow[nazwanie=doma]');

    $find.find("proekt").each(function () { 
    var id = $(this).attr("id") 
    globalid = id;
        $(this).find("type_nr").each(function(i,elem) {
    if($(this).text() == 18) {
           var text = $(this).parent().find("link_fajla").text()
           globaltext = text;
        }

});
globalploshad = $(this).find("ploszad_netto").text()
globalploshad = Math.round(globalploshad*100)/100
    $(".main").append('<div class="book"><div class="title"><strong>' + $(this).find("nazwanie_proekta").text() + '</strong></div><div class="foto"><a href="/proekty/evropejskij-standart/proekt-doma.html?id=' + globalid + '"><img src="' + globaltext + '" width="200"></a></div><div class="cubatura">Площадь ' + globalploshad + ' м<sup>2</sup></div><div class="date">Код проекта: ' + $(this).find("kod_proekta").text() + '</div></div>');
    $(".book").fadeIn(1000);

    });

}
</script>

<div class="main">
<div align="center" class="loader"><img src="loader.gif" id="load" width="200" height="20" align="absmiddle"/></div>
</div>

<div class="clear"></div>

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

В связи с чем вопрос: как ускорить работу этого кода? Может быть, его нужно переписать или сделать постраничную разбивку или еще что-то. Прошу помощи и совета, ну и желательно с кодом. ))

Ответы

▲ 2Принят

@Batyabest, не знаю, будут ли меняться данные в исходном файле или нет, но на данный момент у вас более 550-ти позиций, которые вы собираетесь выводить на экран. Если не выводить изображения, то лично у меня код отрабатывает примерно за 1.2 секунды. Но т.к. каждое фото у вас весит более 100Кб, то можно еще долго сидеть в ожидании, пока все они загрузятся. В общем, я советую вам задуматься о постраничном выводе или постепенной подгрузке очередной порции, по мере прокрутки страницы пользователем.

<?php 
header('Content-Type: text/html; charset=utf-8');
$file = "pg.xml";
$dom = new DOMDocument();
$ies = libxml_use_internal_errors(true);
$dom->loadHTMLFile($file);
libxml_use_internal_errors($ies);
$xpath = new DOMXpath($dom);
$projects = $xpath->query("//grupa_proektow[@nazwanie='doma']/proekt");
$result = '';
foreach($projects as $project){
    $result .= '<div class="book">
    <div class="title"><strong>' . $project->getElementsByTagName('nazwanie_proekta')->item(0)->nodeValue . '</strong>
    </div>
    <div class="foto">
            <a href="/proekty/evropejskij-standart/proekt-doma.html?id=' . $project->getAttribute('id') . '">
                <img src="' . $xpath->query('.//type_nr[contains(text(),"18")]/following-sibling::link_fajla', $project)->item(0)->nodeValue . '" width="200">
            </a>
    </div>
    <div class="cubatura">
            Площадь ' . round($project->getElementsByTagName('ploszad_netto')->item(0)->nodeValue, 2) . ' м<sup>2</sup>
    </div>
    <div class="date">Код проекта: '  . $project->getElementsByTagName('kod_proekta')->item(0)->nodeValue .  '</div>
    </div>';
}
echo $result;

Для того, чтоб вывести, скажем, только первые 10 записей, то добавляем в девятой строке [position() >= 1 and position() < 11]:

/* ... */
$projects = $xpath->query("//grupa_proektow[@nazwanie='doma']/proekt[position() >= 1 and position() < 11]");
/* ... */

UPD Дополнение к комментарию

Предлагаю следующий вариант: парсите XML-файл, когда он меняется, сформированный HTML записываем в отдельный файл в виде JSON-строки. Вытаскивая данные из этого файла, вы будете получать уже готовый к выводу HTML. Для вас, я так понимаю, это будет оптимально. Делаем следующие изменения:

// Вместо
$result = '';
// пишем
$result = array();
// или если PHP 5.4 и выше
$result = [];

// В цикле foreach, так же меняем вместо конкатенации
$result .= 
// на добавление в массив
$result[] =

// В самом низу, вместо вывода
echo $result;
// записываем данные в файл
file_put_contents('data.json', json_encode($result)); // имя файла - любое

Весь код выше, вместе с изменениями, записываете в отдельный файл типа "myXMLparser.php" и запускаете по мере надобности. Теперь о том, как получать данные.

$data = json_decode(file_get_contents('data.json'), 1); // Массив
// или 
$data = json_decode(file_get_contents('data.json')); // Объект

В зависимости от выбранного варианта, в переменной $data, у вас будет или массив, или объект, который можно сразу выводить в цикле на экран. Каждый элемент объекта/массива - это ваш отдельный блок.

▲ 1

Да как так можно писать переменные транслитом, это же такое убожество, вам не стыдно?!

<script>
$(function() {
  $.get("pg.xml", function(xml) {
    $('#load').fadeOut();
    $("#content").html(parseXML(xml));
    $(".book").fadeIn(1000);
  });
});

function parseXML(xml) {
  var html = [],
    id, text, area;
  $(xml).find("grupa_proektow[nazwanie=doma] proekt").each(function() {
    var $this = $(this);
    id = $this.attr("id");

    $this.find("type_nr").each(function(i, el) {
      var $this = $(this);
      if ($this.text() == "18") {
        text = $this.parent().find("link_fajla").text();
      }      
    });

    area = Math.round($this.find("ploszad_netto").text() * 100) / 100;

    html.push([
      "<div class='book'><div class='title'><strong>", $this.find("nazwanie_proekta").text(), 
      "</strong></div><div class='foto'><a href='/proekty/evropejskij-standart/proekt-doma.html?id=", globalid, "'><img src='",
      globaltext, "' width='200'></a></div><div class='cubatura'>Площадь ", globalploshad, 
      " м<sup>2</sup></div><div class='date'>Код проекта: ", $this.find("kod_proekta").text() + "</div></div>"].join());

    return html.join("");
  });
}
</script>

<div class="main">
  <div align="center" class="loader"><img src="loader.gif" id="load" width="200" height="20" align="absmiddle"/></div>
  <div id="content"></div>
</div>

<div class="clear"></div>