Компьютер

ЧП Куликов Михаил Михайлович

Тел:

+380-(50)-589-55-02

Loading
Мы в социальных сетях...

    -  Вконтакте
    -  Facebook
    -  Google+
    -  Twitter
    -  LiveJournal
    -  Я.ру
    -  Одноклассники
    -  RSS
    -  Мой Круг
    -  YouTube
Прочее...

/images/certificate_small.png

Анализ: траст сайта it-kmm.com
Внимание!!! Заработал на 100% новый сервис.

Как сделать xml parser (PHP).

Как сделать xml parser.

Вот и лето пришло и первая неделя июля пролетела незаметно. Через две недели мне защищать свой диплом, а одна из частей его – XML parser. Но жалко, что не в пхп. Ну ниче, счас наверстаем :)

Я видел много xml parser`ов, но не затрагивал при этом веб-программирование. Теперь же я хочу выяснить и научиться вместе с вами, как сделать простой xml parser в php.

А зачем? Надо! :)

Не, ну на самом деле: xml-файлы – очень полезная штука. И любой профессионал должен… нет, не должен, а обязан знать, как с ними работать. Мы же хотим стать профессионалами? Если Вы на моем блоге, то такое желание у Вас есть.

Итак…

Мы предполагаем, что знаем, что такое XML и описывать его здесь не будем. Ну, если не знаем, то легко узнаем здесь: http://ru.wikipedia.org/wiki/XML

При поиске способов парсинга XML на PHP, я обнаружил простой набор функций в PHP для работы с XML-файлами, который называется «XML Parser Functions». Парсинг начинается с инициализации парсера вызовом функции xml_parser_create:

$xml_parser = xml_parser_create();

Потом нам нужно сказать парсеру, какие функции будут обрабатывать попадающиеся ему xml-теги и текстовую информацию в процессе парсинга. Т.е. нужно установить некие обработчики:

xml_set_element_handler($xml_parser, “startElement”, “endElement”);

Эта функция отвечает за установку обработчиков начала элемента и конца элемента. Например, если в тексте xml-файла встретится комбинация, то функция startElement сработает, когда парсер найдет элемент, а функция endElement – при нахождении.

Сами же функции startElement и endElement принимают несколько параметров согласно документации по php:

<?
function startElement($parser, $name, $attrs) {
// $parser - уникальный идентификатор парсера
//     (т.к. мы можем использовать несколько парсеров)
// $name - имя обнаруженного элемента
// $attrs - массив атрибутов обнаруженного элемента
}function endElement($parser, $name) {
// $parser - уникальный идентификатор парсера
// $name - имя обнаруженного элемента
}
?>

А как же считывать данные из файла? Мы же пока не видели ни одного параметра для этого ни в одной из функций! А об этом дальше: считывание файла возлагается на плечи программиста, т.е. мы должны использовать стандартные функции для работы с файлами:

<?
if (!($fp = fopen($file, "r"))) {
die("could not open XML input");
}
?>

Открыли файл. А теперь нужно построчно считывать его и скармливать считываемые строки функции xml_parse:

<?
while ($data = fgets($fp)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
echo "<br>XML Error: ".xml_error_string(xml_get_error_code($xml_parser));
echo " at line ".xml_get_current_line_number($xml_parser);
break;
}
}
?>

Здесь заметим две очень важные вещи. Первая – это то, что функции xml_parse в третьем параметре нужно передать флаг считывания последней строки (true – если строка последняя, false – если нет). Второе – это то, что как и в любом деле, мы должны следить здесь за ошибками. За это отвечают функции xml_get_error_code и xml_error_string. Первая функция получает код ошибки, а вторая – по полученному коду возвращает текстовое описание ошибки. Что в результате возникновения ошибки получится – рассмотрим позже. Не менее полезная функция xml_get_current_line_number скажет нам номер текущей обрабатываемой строки в файле.

И как всегда мы должны освободить занимаемые системой ресурсы. Для парсинга XML – это функция xml_parser_free:

xml_parser_free($xml_parser);

Вот, основные функции мы рассмотрели. Пора бы посмотреть их на деле. Для этого я придумал xml-файл с очень простой структурой:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<info who="моя">
<address ulica="моя улица!!" kvartira="12" dom="15">123</address>
<phone>+71234567890</phone>
</info>
</root>

Назовем этот файл data.xml и попытаемся его распарсить с помощью следующего кода:

<?
function startElement($parser, $name, $attrs) {
global $depth;echo str_repeat("&nbsp;", $depth * 3); // отступы
echo "<b>Element: $name</b><br>";      // имя элемента

$depth++; // увеличиваем глубину, чтобы браузер показал отступы

foreach ($attrs as $attr => $value) {
echo str_repeat("&nbsp;", $depth * 3); // отступы
// выводим имя атрибута и его значение
echo 'Attribute: '.$attr.' = '.$value.'<br>';
}
}

function endElement($parser, $name) {
global $depth;

$depth--; // уменьшаем глубину
}

$depth = 0;
$file  = "data.xml";

$xml_parser = xml_parser_create();

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

if (!($fp = fopen($file, "r"))) {
die("could not open XML input");
}

while ($data = fgets($fp)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
echo "<br>XML Error: ";
echo xml_error_string(xml_get_error_code($xml_parser));
echo " at line ".xml_get_current_line_number($xml_parser);
break;
}
}

xml_parser_free($xml_parser);
?>

В результате разработанного нами простейшего скрипта браузер вывел в свое окно следующую информацию:

Element: ROOT
   Element: INFO
      Attribute: WHO = моя
      Element: ADDRESS
         Attribute: ULICA = моя улица!!
         Attribute: KVARTIRA = 12
         Attribute: DOM = 15
      Element: PHONE

Попробуем испортить XML-файл, заменив тег <phone> на <telephone>, а закрывающий тег оставив прежним:

Element: ROOT
   Element: INFO
      Attribute: WHO = моя
      Element: ADDRESS
         Attribute: ULICA = моя улица!!
         Attribute: KVARTIRA = 12
         Attribute: DOM = 15
      Element: TELEPHONE

XML Error: Mismatched tag at line 5

Ух ты! Сообщения об ошибках работают! Причем довольно информативные.

Эх, я забыл еще одну вещь… Мы же не вывели текст, содержащийся внутри тегов address и phone. Исправляем наш недочет – добавляем текстовый обработчик с помощью функции xml_set_character_data_handler:

xml_set_character_data_handler($xml_parser, ’stringElement’);

И добавляем в код саму функцию-обработчик:

<?
function stringElement($parser, $str) {
if (strlen(trim($str)) > 0) {
global $depth;echo str_repeat("&nbsp;", $depth * 3); // отступ
echo 'String: '.$str.'<br>'; // выводим строку
}
}
?>

Посмотрим теперь на вывод:

Element: ROOT
   Element: INFO
      Attribute: WHO = моя
      Element: ADDRESS
         Attribute: ULICA = моя улица!!
         Attribute: KVARTIRA = 12
         Attribute: DOM = 15
         String: 123
      Element: PHONE
         String: +71234567890

О! Теперь вывели все!

Кстати, кто-нибудь заметил, что имена тегов и атрибутов все большими буквами написаны? Странно… они же в нашем xml-файле малыми буквами обозначены. Видимо где-то какие-то настройки установлены, чтобы делать uppercase…

Ааа, нашел! Оказывается есть еще функция xml_parser_set_option:

xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0);

Таким вызовом мы отменяем вывод имен атрибутов и имен тегов большими буквами:

Element: root
   Element: info
      Attribute: who = моя
      Element: address
         Attribute: ulica = моя улица!!
         Attribute: kvartira = 12
         Attribute: dom = 15
         String: 123
      Element: phone
         String: +71234567890

В этой статье мы рассмотрели самый простой, но для большинства задач достаточный метод вытаскивания информации из XML-файлов. Я еще слышал про какие-то другие более мощные методы, но их буду рассматривать, когда сам изучу немного :)

nika, Вам нужно вставить вызов
xml_set_character_data_handler($xml_parser, ’stringElement’);
после
xml_set_element_handler($xml_parser, “startElement”, “endElement”);

В общем для правильного отображения нужно соблюдать следующее:
1. нужно, чтобы xml-файл был в кодировке UTF-8
2. в xml-файле первая строчка должна быть такой:
< ?xml version="1.0" encoding="UTF-8"?>
3. нужно инициализировать парсер так:
xml_parser_create(”UTF-8?);
4. нужно перед выводом содержимого xml-файла в браузер настроить последний на кодировку UTF-8:
header( “Content-Type: text/html; charset=utf-8?);

Для отображения текста на русском языке используем
iconv(”UTF-8?,”windows-1251?, $attr), где $attr, то что нужно вывести.

Есть такие два класса интересных в стандартной библеотеке PHP5 – DOMDocument() и XSLTProcesor() использовал на довольно крупных проектах – не жалуюсь =)

Вообще у PHP есть еще одна библиотечка для разбора XML по принципу SAX – называется XMLReader.

  • Господа, как вывести из xml с помощью simplexml не стандартные теги, например ?
    Переменная вида $text = $item->yandex:full-text не работает.

  • Юрий
    Октябрь 8th, 2009

    Все ОК, только обратите внимание на наличие следующего параметра,

    function cdata($parser, $cdata)
    {
    var_dump($parser, $cdata);
    }

    xml_set_character_data_handler($this->parser, “cdata”);

    Без него не хочет парсить XML с CDATA…. размером в 1.5 метра

    2Nika, Функция header() работает только в том случае, если до нее не было ничего выведено, то бишь первым действие производили ее, т.к. мы отсылаем заголовки на эту страницу, которые говорят нам, что текст нужно переводить в кодировку UTF-8. Судя по вашей ошибке у вас есть пропуски строк, поэтому сделайте вот так:

    Значение == порядковый номер строки
    <?php 1
    header(”Content-Type: text/html; charset=utf-8?); == 2

    Всё намного проще делается в действительности
    yurban.ru/development/php_xml_parser

     

.



Комментарии к посту «Как сделать xml parser (PHP).»

Комментариев пока нет, будьте первым.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.

DT

Курсы валют:

UAH

1 USD = 24.510 24.096
1 EUR = 27.100 26.525
1 RUR = 00.396 00.356

Антивирусы в формате SaaS
Подписаться письмом

Спонсоры...

SP:   LF:   PP:  

ubuntu == © Куликов М.М. (2011)
Сертифицированный партнер Dr.Web Free secondary DNS uaRating Rambler's Top100 Рейтинг@Mail.ru bigmir)net TOP 100 Яндекс цитирования Ranker Рейтинг сайта в веб-каталоге misto.zp.ua TOP.zp.ua