[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Парсинг XML
Invis1ble
Всем привет! Извиняюсь, если такой вопрос уже рассматривался на форуме, но я даже не знаю, как у поисковика спросить правильно )
Вобщем, такая ситуёвина. Вот код для наглядности:
function openTagHandler($xmlh, $tagName, $tagAttrs)
{
if ($tagName == 'div' && isset($tagAttrs['class']) && $tagAttrs['class'] == 'sr')
{}
}


function closeTagHandler($xmlh, $tagName)
{
}


function dataHandler($xmlh, $data)
{
}


$page = file_get_contents($URI);

$xmlh = xml_parser_create('utf-8') or die('Could not create xml-parser.');

xml_set_element_handler($xmlh, 'openTagHandler', 'closeTagHandler');
xml_set_character_data_handler($xmlh, 'dataHandler');
xml_parser_set_option($xmlh, XML_OPTION_CASE_FOLDING, 0);

if (!xml_parse($xmlh, $page))
die(sprintf("XML parse error: %s on line %d.",
xml_error_string(xml_get_error_code($xmlh)),
xml_get_current_line_number($xmlh)));

xml_parser_free($xmlh);

Вопрос такой: в обработчике openTagHandler() проверяется условие на наличие примерно следующей структуры:
<div class="sr">некоторый текст</div>

- при выполнении этого условия (тег найден), нужно обработать текст, заключенный в этом теге ("некоторый текст"). Как грамотно это сделать?
У меня такая мысль: при выполнении условия в обработчике openTagHandler() установить некоторый глобальный флаг, а в обработчике dataHendler() проверять наличие этого флага... Немного корявенько, как я понимаю... Может есть какое-то более красивое решение?



Спустя 2 часа, 18 минут, 14 секунд (24.01.2011 - 21:25) Invis1ble написал(а):
Че-то не получается ничего с флагом....

Спустя 2 часа, 58 минут, 14 секунд (25.01.2011 - 00:23) kirik написал(а):
Цитата (Invis1ble @ 24.01.2011 - 11:07)
Может есть какое-то более красивое решение?

Угу, есть :) Используй xpath:
$string = <<<HTML
<table class="c_topStrip" cellspacing="0" border=0><!--главное меню-->
<tr>
<td id="corner"></td>
<td id="c_strip" align="right">
<nobr><a href="http://phpforum.ru/index.php?act=boardrules" style="color:White;text-decoration:none;">Правила</a>
<a href="http://phpforum.ru/index.php?act=fav" style="color:White;text-decoration:none;">Закладки</a>
<a href="http://phpforum.ru/index.php?act=rep&CODE=totals">Карма</a>
<a href="http://phpforum.ru/index.php?act=calendar" style="color:White;text-decoration:none;">Календарь</a>
<a href="http://phpforum.ru/journal.php" style="color:White;text-decoration:none;">Журналы</a>
<a href="http://phpforum.ru/index.php?act=Help" style="color:White;text-decoration:none;">Помощь</a>
<a href="http://phpforum.ru/index.php?act=Search&f=14" style="color:White;text-decoration:none;">Поиск</a>
<a href="http://phpforum.ru/txt/" style="color:White;text-decoration:none;">PDA</a>
<a href="http://phpforum.ru/chat/" title="Чат" style="color:White;text-decoration:none;"> Чат</a></nobr>
<div class="sr">некоторый текст</div>
</td>
</tr>
</table>

HTML;

$DOM = new DOMDocument();
$DOM->loadHTML($string);
$xpath = new DOMXpath($DOM);

$elements = $xpath->query('//div[@class="sr"]');

foreach($elements as $element) {
echo $element->nodeValue . '<br />';
}

Спустя 2 часа, 54 минуты, 43 секунды (25.01.2011 - 03:18) Invis1ble написал(а):
kirik
ага, спасибо, я уже юзаю, только не Xpath (щас и его попробую =)), а класс DOMDocument()... Вобщем, щас буду проводить клинические испытания на основе твоего примера ))

Спустя 1 час, 54 минуты, 52 секунды (25.01.2011 - 05:13) Invis1ble написал(а):
kirik
Попробовал. Очень удобно. Буду учить синтаксис запросов.
у меня такой вопрос: а как насчет производительности? В смысле, если требуется распарсить к примеру 100 000 документов (тот же форум), то насколько целесообразно юзать XPath?
Это на всякий случай я спрашиваю, т.к. сам я думаю, что целесообразней других способов....

Спустя 24 минуты, 10 секунд (25.01.2011 - 05:37) kirik написал(а):
Invis1ble
По производительности не знаю.. не измерял. Но всё таки думаю что должно быть быстрее своей реализации на чистом php.

Спустя 23 минуты, 20 секунд (25.01.2011 - 06:01) Invis1ble написал(а):
kirik
ясно, спасибо

Спустя 3 часа, 53 минуты, 37 секунд (25.01.2011 - 09:54) linker написал(а):
Invis1ble
Учти, что мало кто соблюдает стандарт XHTML при верстки своих сайтов. Любой незакрытый тэг аля <br>, сгенерит эксепшен.

Спустя 7 часов, 32 минуты, 32 секунды (25.01.2011 - 17:27) Invis1ble написал(а):
linker
Я соблюдаю всегда =)
А если серьезно - то я это прекрасно понимаю, но если работать через $DOM->loadHTML($string) или $DOM->loadHTMLFile($file), то насколько я понял невалидный XHTML тоже прокатит без происшествий... Так?

Спустя 2 минуты, 27 секунд (25.01.2011 - 17:29) linker написал(а):
У меня что-то у меня вроде не вышло подсунуть кривой HTML.

Спустя 12 минут, 24 секунды (25.01.2011 - 17:42) Invis1ble написал(а):
linker
странно... Я вот щас проверил специально, убил закрывающий </html>, добавил <br> и еще всяких пакостей подобных - никаких эксепшнов, все вроде норм...
А насколько кривой html ты пробовал? можешь прмер сюда выложить?

Спустя 9 минут, 59 секунд (25.01.2011 - 17:52) linker написал(а):
Invis1ble
Эх, если б я помнил. Надоть будет потренироваться еще.

Спустя 1 час, 5 минут, 48 секунд (25.01.2011 - 18:57) Invis1ble написал(а):
Возник еще вопрос. Вот такой код:
$DOM = new DOMDocument();

$DOM->loadHTMLFile($URI) or die('Could not load HTML identified by ' . $URI);
$DOM->preserveWhiteSpace = false;

$Xpath = new DOMXPath($DOM);

$highlightTags = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'b', 'strong');
$blocks = $Xpath->query('//div[@class="target"]');

foreach ($blocks as $block)
{
foreach ($highlightTags as $highlightTag)
{
$highlightElements = $block->getElementsByTagName($highlightTag);

foreach ($highlightElements as $highlightElement)
$highlightText[] = $highlightElement->nodeValue; // как удалить из DOM текущий элемент?
}
}

записываю в массив текст во всретившихся тегах ($highlightTags) и нужно после этого убрать из DOM совпавшие элементы... Надеюсь, понятно объяснил. Как это сделать?

Спустя 3 часа, 21 минута, 15 секунд (25.01.2011 - 22:19) kirik написал(а):
Invis1ble
Ну дык это же обычный DOM. И работай с ним как с DOM'ом :)
    foreach ($highlightElements as $highlightElement) {
$highlightText[] = $highlightElement->nodeValue; // как удалить из DOM текущий элемент?
$highlightElement->parentNode->removeChild($highlightElement); // как-то так
}

Спустя 1 час, 22 минуты, 53 секунды (25.01.2011 - 23:41) Invis1ble написал(а):
kirik
блин, я примерно так и делал, но не получалось.... Спасибо, за подсказку )

Спустя 48 минут, 17 секунд (26.01.2011 - 00:30) linker написал(а):
При использовании XPath есть грабли с удалением/редактированием/добавлением в полученном наборе узлов, но опять же могу ошибаться, читал об этом давно.


_____________

Профессиональная разработка на заказ

Я на GitHub | второй профиль

Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.