Разбор большого XML-файла с помощью SAX & amp; XPATH

У меня есть код ниже, который разбирает XML-файл и извлекает дочернюю информацию на основе другого дочернего значения.
Код работает хорошо, но мой XML-файл имеет более 200 МБ, и когда я пытаюсь проанализировать и получить несколько данных, сайт загружается в течение 4 минут или более 🙁

$dom    = new DOMDocument();
$xpath  = new DOMXPath($dom);
$reader = new XMLReader();
$reader->open('http://www.bookingassist.ro/test/HotelsPro.xml');
while ($reader->read()) {
if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'Hotel') {
$node = $dom->importNode($reader->expand(), true);
$dom->appendChild($node);
$h1name = $xpath->evaluate('string(/Hotel[HotelCode = "'.$hotelCodes[0].'"]/HotelName)', $node);
$dom->removeChild($node);
if ($h1name) {
$reader->close();
break;
}
}
}

Как я могу разобрать этот документ, чтобы получить данные быстрее. Поскольку я искал по интернету, SAX будет делать то, что нужно, но я не имею ни малейшего представления о том, как его использовать.
Спасибо за ваше время.

1

Решение

Парсер DOM загружает данные в память. SAX-парсер — это потоковый парсер, который я считаю очень быстрым и эффективным.

Сложность парсера SAX заключается в том, что вам необходимо знать имена тегов и собирать данные при потоковой передаче через XML.

Вам нужно настроить три функции, чтобы использовать SAX-парсер …

  1. Первая функция, которая вызывается начальным элементом XML (открывающий тег). Эта функция возвращает имя открывающего тега и любые атрибуты.

    Функция startElement ($ xml_parser, $ name, $ attribute)

  2. Вторая функция, которая вызывается конечным элементом XML (закрывающий тег). В этой функции возвращается только имя закрывающего тега.

    Функция endElement ($ xml_parser, $ name)

  3. Наконец, третья функция для обработки символьных данных, которые передаются между начальным и конечным элементами (открывающий и закрывающий теги).

    функция characterData ($ xml_parser, $ data)

Вам нужно будет поместить свою логику в эти три функции, чтобы выполнять работу, сохраняя любую информацию, которая вам нужна, на лету. Используйте функцию CASE, чтобы делать разные вещи, когда вы приходите к разным открывающим или закрывающим тегам.

Когда у вас есть свои функции, вы можете инициализировать парсер …
Вы должны использовать имена функций в xml_set_element_handler и xml_set_character_data_handler опции.

        //Initialise SAX parser
$xml_parser = xml_parser_create("UTF-8"); //With UTF8 encoding

//Set parser options
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true); //This is a default setting of making all tags uppercase, if set to false you will get the tag name as it's set in the XML.
xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, true); //This should skip values with no values
xml_parser_set_option($xml_parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); //Set the output as UTF-8

xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");

Теперь вы можете открыть поток ….

$ Xml-> открытая (»http://www.bookingassist.ro/test/HotelsPro.xml«);

И вы анализируете данные.
Одна из трех функций будет запускаться в зависимости от того, является ли это начальным тегом, конечным тегом или символьными данными.

while ($data = read($xml, 4096))
{
if (!xml_parse($xml_parser, $data, feof($xml)))     {
echo "Error in the XML data\t" . xml_error_string(xml_get_error_code($xml_parser)));
break;
}

}

Как только парсер закончил, освободите ресурсы с помощью ….

xml_parser_free($xml_parser);
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]