Модераторы: Aliance, skyboy, MoLeX, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Опыт парсинга XHTML, пара советов по парсингу XHTML 
:(
    Опции темы
MyDarkSide
Дата 8.5.2008, 23:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 69
Регистрация: 21.3.2008

Репутация: нет
Всего: -1



Недавно пришлось усердно парсить XHTML через PHP. может мой опыт кому то пригодиться. Для профи скорее всего это не будет откровением, но новичкам кое-чем поможет.
И так первое, если парсить XHTML (или XML) предполагается DOM парсером, убедитесь что перед определением  
Код

"<?xml version="1.0" encoding="Windows-1251"?>"

нет никаких символов в том числе пробелов! иначе это вызовет ошибку и парсер остановиться. Я решаю эту проблему так:
Код

<?php
  $xml = file_get_contents('file.xml');
  $xml = trim( $xml );
?>
 
Второе. Очень часто XHTML надо пропарсить так, что бы получить ассоциативный массив, где ключами выступают тэги. Задача осложняется тем, что XHTML может содержать тэги которые просто указывают на форматирование данных, но не на их структуру (<small> <br/> и т.д.). в этом случае массив зассоряется не нужными ключами. Еще хуже если  расположение форматирующих тэгов носит не регулярный характер, например
Код

<p><b>Фирма</b></p>
<p>Контакты:</p>
<p><small>г.Славный ...</small></p>
<a href='..'>www.site456.ru</a>
 
в этом случае после парсинга данные в массиве оказываются на разном уровне вложенности:
Код

$array['p'][0]['b'] ; // здесь "Фирма"
$array['p'][1] ; //здесь "Контакты"
$array['p'][2]['small']; //здесь "г.Славный..."
$array['a'][0] ; // здесь www.site456.ru


Работать с таким массивом потом "одно удовольствие". Кроме того, для парсинга такого XHTML не обойтись без рекурсивного обхода в глубину, что медленно и требует памяти, особенно для структур с глубокими вложениями.
Я советую перед тем как скармливать XHTML парсеру (не важно как он выполнен) провести предварительную подготовку данных, так что бы он не  много похудели:
Код

<?php
$xml = file_get_contents('file.xml');
$xml = trim( $xml );
$trash = array('<small>','</small>','<br/>','<b>','</b>');
$xml = str_replace($trash, '', $xml);
?>

В массиве $trash указываем какие тэги надо вырезать, приведенное решение не идеальное, универсальнее использовать регулярки для удаления действительно парных тэгов, но они гораздо медленее. Главное что нужно помнить при таком подходе что в $trash надо указывать тэги которые не содержат в себе аттрибутов (в вашем документе), иначе фильтр сработает не правильно. Если вы используете в парсере метод getElementsByTagName(name) - то вырезать <name> естественно нельзя.
Что дает предварительная фильтрация: при правильном указании засоряющих тэгов гораздо снижается размер парсируемого документа -> меньше требуется времени и памяти. Структура документа упрощается и в некоторых случаях можно вообще обойтись без рекурсивного обхода. Если в документе ищется определенная инфа через регулярки - упрощается их шаблон. 
Вообще предварительной подготовке данных перед парсингом следует уделять внимание, это может очень помочь впоследствии.
Третье. Многие знают, но тем не менее периодически многие же наступают на эти грабли: по умолчанию в XML (XHTML естественно тоже) пробел между тэгами воспринимается как текстовый тэг! 
Код

<span>  <b>текст</b></span>

внутри тэга span два тэга! #text и #b и если обратиться к свойству nextSibling->nodeValue (DOM PHP5)  узла span то оно вернет пробел вместо ожидаемого "текст".
Чтобы этого избежать необходимо свойство preserveWhiteSpace экземпляра класса domDocument установить в false
Код

<?php
// для php ver. 5
$dom=new domDocument();
$dom->preserveWhiteSpace=false;
?>
  
К сожалению, у меня были случае когда этот прием не срабатывал по неизвестной причине. Так что возможно об этом следует позаботиться самому и включить вырезание лишних пробелов в предварительную подготовку данных. 


PM ICQ   Вверх
SelenIT
Дата 9.5.2008, 00:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


баг форума
****


Профиль
Группа: Завсегдатай
Сообщений: 3996
Регистрация: 17.10.2006
Где: Pale Blue Dot

Репутация: нет
Всего: 401



Имхо, для фильтрации и выделения нужного куска X(HT)ML удобнее использовать XSLT, а не регулярки. Тогда и с атрибутами морочиться не надо...


--------------------
Осторожно! Данный юзер и его посты содержат ДГМО! Противопоказано лицам с предрасположенностью к зонеризму!
PM MAIL   Вверх
MyDarkSide
Дата 9.5.2008, 17:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 69
Регистрация: 21.3.2008

Репутация: нет
Всего: -1



SelenIT, 
спору нет PHP5 + XML +XSLT - мощнейший инструмент, но как с любым мощным инструментом с ним надо уметь обращаться, а для новичка написать правильный xsl шаблон не совсем просто.
А я предложил простое и быстрое решение (как всегда в жертву приноситься универсальность, но тут уж ничего не поделаешь,  как всегда,  или одно - или другое :(  ). 
Вырезке здесь подвергаются тэги (именно тэги) которые редко используются с какими-либо атрибутами - типа <b>, <u>, <strong> и т.д. в то же время если тэг содержит какой-нибудь аттрибут, то лучше этот тэг не вырезать, в аттрибуте может оказаться очень важная информация.   
PM ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: X технологии | Следующая тема »


 




[ Время генерации скрипта: 0.0486 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.