killich@yandex.ru
Добрый день!
Данную тему предлагаю тем, кто еще ни разу не встречался с XML парсингом. Сам только что с ним познакомился и хочу поделиться с тамими же как я чайниками тем, что у меня получается. Хочу надеятся, что им это поможет. Пусть профи не ругаются, если я чего не понимаю в XML и парсинге. К каждому утверждению, сделанному мною далее предлагаю делать добавку - мне так кажется. Ну, а если кажется, то перекрестимся и начнем... ;0)
Парсинг, фактически, это разбор некоторого файла на состовляющие элементы для того, что бы потом эти элементы использовать в своих корыстных целях.
XML это язык разметки, *цензура*ожий на HTML, но более обширный по своим пременениям. XML часто используют для передачи данных от одной системы к другой. Взаимодействие между разнородными системами, как правило, не определено, а потому потребовался обобщенный способ передачи данных. Под системами я, в основном, подразумеваю базы данных.
Для парсинга в PHP можно использовать встроенные функции:
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, НАЗВАНИЕ_ОПЦИИ, ЗНАЧЕНИЕ);
xml_set_element_handler($xml_parser, "FunctName1", "FunctName2");
xml_set_character_data_handler($xml_parser, "FunctName3");
xml_parse($xml_parser, $data, feof($fp))
xml_parser_free($xml_parser);
Если надо подробнее найдите эти ф-ии в доках.
Предположим, что некоторая система сгенерировала следующий файл с данными:
*** one.xml ***
123-456-87
436-434-76
555-666-999
Вот это и есть XML файл. Даже не вооруженным глазом видно, как организованна информация.
Наша задача, разобрать этот файл, извлеч данные и поместить на web страницу.
Что бы на сайте что-то появилось нужен вот такой шаблон:
*** index.php ***
// Имя файла, который будем читать
$file = "one.xml";
function startElement($parser, $name, $attrs)
{
// Эта ф-ия работает при встрече открывающего тега
}
function endElement($parser, $name)
{
// Эта ф-ия работает при встрече закрывающего тега
}
function characterData($parser, $data)
{
// Эта ф-ия работает с данными внутри тега
}
// Создаем парсер
$xml_parser = xml_parser_create();
// Настраиваем его (не чувствителен к регистру)
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
// Указываем ф-ии обработки начального тега и конечного тега (см. выше)
xml_set_element_handler($xml_parser, "startElement", "endElement");
// Ф-ия обработки данных внутри тега (см. выше)
xml_set_character_data_handler($xml_parser, "characterData");
// Открываем файл
if ( !($fp = fopen($file, "r")) )
{ die("could not open XML input"); }
// Читаем файл и парсингуем
while ($data = fread($fp, 4096))
{
if ( !xml_parse($xml_parser, $data, feof($fp)) )
{
// Сообщение если возникла ошибка парсинга
die(
sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser))
);
}
}
// удаляем парсер, он сделал свое дело ;0)
xml_parser_free($xml_parser);
?>
Если запустите index.php, то ничего не увидете.
Пусть мы хотим увидеть названия тегов и данные в них. Измените функции след. образом.
function startElement($parser, $name, $attrs)
{
print "Открыт тег ". $name . "
";
}
function endElement($parser, $name)
{
print "Закрыт тег " . $name . "
";
}
function characterData($parser, $data)
{
print "".$data. "
";
}
Запускаем index.php. Видим на странице след. результат:
Открыт тег BOOKDB
Открыт тег BOOK
Открыт тег AUTHOR
Jhon Smith
Закрыт тег AUTHOR
Открыт тег BOOKNAME
Mega Book
Закрыт тег BOOKNAME
Открыт тег CODE
123-456-87
Закрыт тег CODE
Открыт тег GANRE
fantastic
Закрыт тег GANRE
Закрыт тег BOOK
.
// прочие данные из one.xml
.
Открыт тег PRICE
15$
Закрыт тег PRICE
Закрыт тег BOOK
Закрыт тег BOOKDB
Все остальное достаточно просто, вы можете определить, как поступать с любым из элементов: вывести на страницу, не вывести, выделить его жирным или сделать из него ссылку - все это ваша фантазия. Основа у вас есть, как это все работает можно понять и самому ( я же понял... надеюсь ;0) ). На этом практически все, но еще немного об атрибутах тегов.
Атрибуты открывающего тега:
Иногда в первом теге определяют атрибуты, ну, например, в HTML так размечена таблица:
<table width="400" border="1" cellspacing="0" cellpadding="0" >
<tr >
<td >1111</td >
<td >2222</td >
<td >3333</td >
</tr >
</table >
Здесь width="400" border="1" cellspacing="0" cellpadding="0" - это атрибуты тега и их значения. Эти данные так же можно извлеч при парсинге, т.к. ф-ия отвечающая за открывающий тег обозначена след. образом:
function startElement($parser, $name, $attrs)
Здесь $name - имя самого открывающего тега, а $attrs - это массив атрибутов. О работе с массивами писать не буду ;0) . Если в теге определен хотя бы один атрибут, то этот массив будет не пустой.
******************************
Кстати, не обязвтельно ф-ия startElement() должна иметь такое имя, можно назвать ее и по другому, только зарегистрируйте ее в ф-ии :
// Указываем ф-ии обработки начального тега и конечного тега (см. выше)
xml_set_element_handler($xml_parser, "ИМЯ_ФУНКЦИИ1", "ИМЯ_ФУНКЦИИ2");
******************************
Определите ф-ии обработки след. образом:
function startElement($parser, $name, $attrs)
{
print "
TEG is ";
print "".$name . "";
// Каждый атрибут представим в виде пары
// имя атрибута $n и его значение $v и печатаем эти данные
foreach ( $attrs as $n => $v)
{
print " {". $n ."} = " . $v;
}
print "
";
}
function endElement($parser, $name)
{
print " TEG " . $name ." is closed " ;
print "
";
}
function characterData($parser, $data)
{
print "".$data."
";
}
Дальше можно сделать следующее. Возмите html файл и прогоните его через этот парсер, посмотриче, что получится. А получится довольно интересно, например:
TEG is A {HREF} = index.html
Front page
TEG A is closed
При парсинге можно находит на указанной странице все ссылки и сохранять их адреса. Зачем это может пригодится не знаю, но возможность такая есть ;0)
Главное при парсинге HTML, да и любой другой разметки, что бы она соответствовала стандарту. Т.е. теги не тр*цензура*ющие в HTML закрытия:
, ,
и и некоторые другие, были записаны по след. стандарту:
, ,
и .
А атрибуты тегов обязательно оформлялись в кавычки, вот так:
<table width="400" border="1" cellspacing="0" cellpadding="0" >
а не так:
<table width=400 border=1 cellspacing=0 cellpadding=0 >
Иначе парсер выдаст ошибку и заглохнет.
Ну, вроде, все... строго не судите... удачи!
_____________
Аксиома Дучарма:
Если рассмотреть проблему достаточно внимательно, то Вы увидите себя, как часть этой проблемы.