В статье рассматривается
методика организации кроссплатформенного межзадачного обмена
данными на основе XML с применением WDDX-пакетов. Приведенные
примеры демонстрируют возможность как формирования входных
документов, так и загрузки массивов в формате XML+WDDX в
PHP-приложение.
Одна из весьма серьезных проблем,
возникающих при Web-программировании заключается в
необходимости стыковки между расличными задачами
(программами), объединяемыми в Internet/Intranet-систему.
Например, при разработке сложных систем, которые ведутся в
несколько этапов различными коммандами разработчиков, может
возникнуть ситуация, при которой часть модулей реализована на
Perl, а часть - на PHP.
Достаточно удобное решение
возникающих в такой ситуации многочисленных проблем, которое
было предложено фирмой Allaire, разработчиком известной
инструментальной системы Gold Fusion, основано на формате XML.
А точнее на одном из его расширений.
WDDX (Web Distributed
Data eXchange - обмен данными, распределенными в сети),
является производным от XML и предоставляет достаточно удобный
механизм, позволяющий конвертировать структуры данных из Perl,
Javascript или PHP в некоторый унифицированный формат на базе
XML или обратно. (В отличие от пакета Gold Fusion, WDDX
выпущен как проект с открытым кодом. Вы можете загрузить WDDX
SDK с сервера http://www.openwddx.org. А при необходимости
обеспечить работу с WDDX из программы на Perl, воспользуйтесь
модулем WDDX.pm с CPAN.)
1. Первое знакомство с
WDDX
Главное преимущество WDDX заключается в
прозрачной для программиста поддержке не только разнообразных "элементарных" типов данных: строк,
чисел, логических значений, даты и времени, но и составных -
массивов, структур и записей. Кроме того, WDDX позволяет
представлять и двоичные данные, например, графические
изображения. Естественно, поддерживается как вывод, так и ввод
данных.
По умолчанию, поддержка WDDX в PHP отключена,
чтобы ее активизировать и иметь возможность проверить
работоспособность примеров этой статье, вы должны
перекомпилировать PHP-машину с конфигурационным ключом
--enable-wddx.
После перезагрузки WWW-сервера с поддержкой
WDDX мы можем приступить к изучению возможностей этого
протокола. Вначале попробуем сериализировать (преобразовать в
формат, пригодный для обмена) одно отдельное значение.
Хитрость WDDX, которая находит отражение в терминологии,
состоит в том, что исходные данные преобразуются в так
называемые "пакеты данных", которые
инкапсулируют имя переменной, её тип и значение.
Поэтому
приведенная ниже программа:
<?php
print
wddx_serialize_value("Преобразование
PHP в WDDX", "PHP
пакет");
?> |
приведет к формированию пакета (текстовой строки):
<wddxPacket version='1.0'>
<header comment='PHP пакет'/>
<data>
<string>
Преобразование
РНР в WDDX
</string>
</data>
</wddxPacket> |
Итак, что мы видим...
Вначале в поток помещен тэг, представляющий собой
идентификатор версии протокола WDDX. Версия 1.0 является
единственной существующей, поэтому просто принимайте эту
информацию к сведению. Затем следует комментарий, в котором
содержится либо описание переменной, либо иногда помещается
имя переменной, в которой хранились данные в исходной
программе. А уже затем следует тэг (в данном случае
<string>), который определяет тип
переменной и её значение.
Но использовать WDDX для
хранения отднльных, изолированных переменных на практике не
слишком удобно. Поэтому в WDDX предусмотрен механизм
"накопления" переменных, подлежащих
сериализации, с последующим помещением их
"в один флакон". Вот как это выглядит на
практике:
<?php
$pi = 3.1415926;
// Создаем пакет, в который будем
сбрасывать данные
//
Сразу же определяем его заголовок, в котором обычно
// помещается назначенние
и/или происхождение пакета
$packet_id=wddx_packet_start("PHP");
//
добавляем первую переменную
wddx_add_vars($packet_id,"pi");
// А теперь определим массив $cities
$cities=array("Austin", "Novato", "Seattle");
// и тоже сбросим его в пакет
wddx_add_vars($packet_id, "cities");
// теперь закрываем (и формируем) пакет
$packet=wddx_packet_end($packet_id);
// это большая строка, в которой
содержится все
//
помещенные в пакет переменные
print $packet;
?> |
В результате выполнения
этой программы вы получите следующий пакет WDDX:
<wddxPacket
version='1.0'><header comment='PHP'/>
<data>
<struct>
<var
name='pi'><number>3.1415926</number>
</var>
<
name='cities'>
<array length='3'>
<string>Austin</string>
<string>Novato</string>
<string>Seattle</string>
</array>
</var>
</struct>
<data>
<wddxPacket> |
2. Функции
WDDX-генератора и анализатора
Теперь давайте
приступим к подобному обсуждению функций WDDX.
2.1
Сериализация переменной - wddx_serialize_value
string wddx_serialize_value
(mixed var [, string comment]) |
Функция
wddx_serialize_value() используется для создания WDDX пакета,
содержащего одно единственое значение. Это значение
извлекается из переменной var, а при наличии необязательного
комментария comment, он добавляется в заголовок пакета.
Результатом работы функции является сформированный WDDX-пакет.
2.2 Сериализация множества -
wddx_serialize_vars
string wddx_serialize_vars
(mixed var_name [, mixed ...]) |
Функция
wddx_serialize_vars() предназначена для создания пакета WDDX,
в котором содержится структура с сериализованным
представлением множества переменных, переданный в качестве
аргументов функции.
Функция принимает переменное
количество аргументов, каждый из которых может представлять
собой либо строку, значение которойявляется именем переменной,
подлежащей помещению в пакет, либо массив, элементы которого
являются именами переменных или массивов, которые содержат
такие имена и т.д. В общем рекурсивные возможности функции, на
которые несомненное влияние оказал Лисп, предоставляют широкий
простор для деятельности...
Вот так эта функция может
использоваться в прикладной программе:
<?php
$a=1;
$b=5.5;
$c=array("blue","orange","violet");
$d="colors";
$clvars=array("c","d");
print
wddx_serialize_vars("a","b",$clvars);
?> |
В результате выполнения
этого примера будет сформирован следующий пакет WDDX:
<wddxPacket version='1.0'>
<header/>
<data>
<struct>
<var
name='a'>
<number>1</number>
</var>
<var
name='b'>
<number>5.5</number>
</var>
<var
name='c'>
<array length='3'>
<string>blue</string>
<string>orange</string>
<string>violet</string>
<array>
<var>
<var
name='d'>
<string>colors</string>
</var>
</struct>
</data>
</wddxPacket> |
2.3 Создание нового
пакета - wddx_packet_start
int wddx_packet_start ([string
comment]) |
Функция
wddx_packet_start() используется для создания нового пакета
WDDX, предназначенного для накопления в нем нескольких
переменных. Функция может принимать дополнительный аргумент
comment, в который помещается необязательный комментарий
(описание пакета). По завершению работы функция возвращает
целочисленный идентификатор пакета, который используется при
работе функций заполнения. Определение всех необходимых
структур данных, необходимых для хранения помещаемых в пакет
переменных, будет выполняться автоматически.
2.4
Закрытие пакета - wddx_packet_end
string wddx_packet_end (int
packet_id) |
Функция
wddx_packet_end() завершает обработку пакета WDDX,
идентифицируемого с помощью packet_id и возвращает строку,
содержащую сформированный пакет.
2.5 Добавление
данных в пакет - wddx_add_vars
wddx_add_vars (int packet_id,
mixed name_var [, mixed ...]) |
Функция wddx_add_vars()
используется для сериализации переданных ей аргументов с
помещением в открытый ранее пакет с идентификатором id.
Переменные, которые подлежат сериализации, определяются так
же, как и в функции wddx_serialize_vars().
2.6
Восстановление данных - wddx_deserialize
mixed wddx_deserialize (string
packet) |
Функция
wddx_deserialize() принимает в качестве аргумента строку,
содержащую пакет WDDX, анализирует ее и восстанавливает
переменные, содержащиеся в ней. Возвращаемый результат может
представлять собой строку, число или массив. Сложные структуры
данных при восстановлении помещаются в ассоциативные массивы.
3. Генерация системного журнала в XML+WDDX
Теперь, в качестве иллюстрации, рассмотрим
практический пример работы подсистемы обработки ошибок в РНР
(Листинг 1). Мы создадим собственную функцию обработчика
ошибок, которая будет генерировать журнал, представленный в
модном XML-формате, а также отправлять письмо администратору
узла при обнаружении критических ошибок. Поскольку нам
придется иметь дело с массивами, для их помещения в журнал мы
воспользуемся WDDX.
Возможно, пример покажется вам
достаточно длинным, но, поверьте, дело того стоит...
Состоит он из двух основных частей - формирования журнала
и его последующего просмотра. Поскольку пользователь nobody,
от имени которого обычно запускаются PHP-программы на сервере
Apache, не имеет особых прав на работу с файловой системой,
для размещения системного журнала мы будем использовать
каталог tmp. В некоторых версиях Linux доступ на запись в этот
каталог
"посторонним" пользователям
закрыт. Поэтому вам может потребоваться изменить права доступа
к нему с помощью команды (такая комманда - это грубейшее
нарушение безопасности и не рекомендуется проводить на узлах,
подключенных с сети Интернет)
chmod a+w /tmp
Обратите
внимание на команду unlink в самом начале программы. Дело в
том, что XML-документ может содержать только один элемент
верхнего уровня, а команда error_log осуществляет
\textit{дописывание в конец существующего файла}. Поэтому,
если вы не будете создавать системный журнал заново, то
выполнить программу больше одного раза просто не сможете -
анализатор XML аварийно завершит работу при обнаружении
второго документа верхнего уровня.
После этого мы создаем
новый файл журнала и помещаем в него открывающий тег
<ERRORLOG>. Затем устанавливаем
свой собственный обработчик ошибочных ситуаций, в задачу
которого входит сформировать запись в XML-формате, которая
будет записана в журнал.
До тех пор, пока структура записи
определена достаточно жестко:
<ERRORLOG>
<ERRORENTRY>
<DАТЕТIМЕ>Дата и время
события</DАТЕТIМЕ>
<ERRORNUM>Koд
ошибки</ERRОRNUM>
<ERRORTYPE>Kaтeгopия</ERRORTYPE>
<ERRORMSG>Cooбщeнue об
ошибке</ЕRRОRMSG>
<SСRIРТNAМЕ>Файл. в
котором зафиксирована ошибка</SСRIРТNAМЕ>
<SCRIPTLINENUM>Hoмep строки в <j>aline</SCRIPTLINENUM>
</ERRORENTRY> |
И никакой необходимости
в использовании WDDX не возникает. Эти данные без особых
проблем считываются и разбираются анализатором XML. Но в
некоторых ситуациях нам бы хотелось, чтобы в системный журнал
наряду с текстом сообщения об ошибках помешались также
значения переменных, действующих на момент возникновения этой
ошибки. Стандартный механизм обработки ошибочных ситуаций
PHP-машины этой информации нам не дает.
Но мы сможем
справиться с этой проблемой и самостоятельно... Для этого нам
достаточно всего трех строчек:
$еrr
.= "\t<VARTRACE>":
$err .= wddx_serialize_value($vars,"Variables");
$err .= "</VARTRACE>\n"; |
В результате мы создаем
собственный элемент XML-документа
<VARTRACE>. внутри которого
поместим WDDX-пакет, составленный из списка локальных
переменных (аргумент
$vars,
определенных в процедуре в момент обнаружения ошибки. Понятно,
что и имена, и значения этих переменных будут меняться от
функции к функции и от ошибки, к ошибке. Но для нас важно
другое - РНР-машина автоматически формирует WDDX-пакет
(который представлен в унифицированном, кроссплатформенном
формате) и затем помещает его в выходной файл. В результате мы
получаем запись вида:
<ERRORENTRY>
<DATETIME>09-Aug-2001
10:44:42</DATETIME>
<ERRORNUM>512</ERRORNUM>
<ЕRRORTYPE>Предупрехдение
пользователя</ЕRRORTYPE>
<ERRORMSG>2-я координата
вектора 1 не является чиспом</ERRORMSG>
<SCRIPTNAME>/usr/local/apache/htdocs/php/part2/error-proc.php</SCRIPTNAME>
<SCRIPTLINENUM>107</SCRIPTLINENUM>
<VARTRACE><wddxPacket
version='1.0'>
<header>
<comment>Variables</comment>
</header>
<data>
<struct>
<var
name='vect1' >
<array length='3'>
<number>2</number>
<number>3</number>
<string>foo</string>
</array>
</var>
<var
name='vect2'>
<array length='3'>
<number>5.5</number>
<number>4.3</number>
<number>-1.6</number>
</array>
</var>
<var
name='i'>
<number>2</number>
</var>
<var
name='c1'>
<string>foo</string>
</var>
<var
name='c2'>
<number>-1.6</number>
</var>
<var
name='d'>
<number>0</number>
</var>
</struct>
</data>
</wddxPacket>
</VARTRACE>
</ERRORENTRY> |
Как видите, WDDX-пакет
органично помещается внутрь XML-документа, что одновременно и
хорошо, и плохо. Хорошо с той точки зрения, что позволяет
аккуратно закруглить (как это сделано в большинстве книг и
руководств по РНР) обсуждение вопроса, заявив, что
использование функции wddx_desrialize() автоматически решит
все ваши проблемы. А плохо потому, что это на самом деле не
так, и анализ XML-документа со встроенными пакетами WDDX
реализуется не столь прямолинейно, как нам хотелось бы.
Собственно говоря, именно поэтому в рассматриваемый нами
пример я включил и собственную версию анализатора на базе
библиотеки Expat, ориентированную именно на обработку
сгенерированного нами файла.
Проблема заключается именно в
том, что теги WDDX ничем по сути не отличаются от тегов XML, a
следовательно, они будут автоматически обрабатываться
обработчиками событий. Но так ли это здорово на самом деле?
Ведь чтобы разобрать XML-документ с вложенными WDDX-пакетами
вам потребуется фактически самостоятельно реализовать
обработку тегов WDDX внутри анализатора? При этом вам не
удастся
"просто так" получить
исходный код пакета, который можно одним вызовом функции
превратить в структуру данных, аналогичную той, которая
использовалась для синтеза пакета. Но разве мы за это
боролись?
Единственное достаточно компактное решение
состоит в том, что мы в процессе анализа восстанавливаем текст
WDDX-пакета со всеми его атрибутами, а после завершения его
сборки (о чем нам сигнализирует тег
</VARTRACE>) мы разбираем
полученный нами пакет функцией wddx_deserialize, а уже затем
извлекаем из нее список переменных и их значения.
Как
видите, нам удалось реализовать механизм отладки программы,
который позволяет старым добрым методом контрольной печати
вскрыть практически любые ошибки времени исполнения программ.
Но гораздо важнее, что теперь в вашем распоряжении имеется
механизм, позволяющий полностью реализовать межзадачный обмен
данными - как из приложения на РНР, так и загрузить данные из
внешнего мира.
Литература
o [Vodolaz2000]
В.Барсуков, В.Водолазкий Интегральная безопасность в системах
и сетях передачи данных. М.: Knowledge, 2000, 450 стр.
o
[Vodolaz2001] В.Водолазкий, А.Колядов Путь к Linux, изд. 2-е,
М.: Knowledge, 2001, 560 стр.
o [XML2000] Н.Питц-Моултис,
Ч.Кирк XML: Современная технология создания документов для
Internet - С-Пб.: БХВ-Петербург, 2000, 736 стр.
o
[php2001] Т.Ратшиллер, Т.Геркен РНР4: Разработка
Web-приложений, С-Пб.: Питер, 2001, 384 стр.
o
[Huews-2001] С.Хьюз, А.Змиевский РНР. Руководство
разработчика, К.: Diasoft, 2001, 380 стр.
Листинг 1.
Пример программы, генерирующей системный журнал.
<HTML>
<ТITLE>Генератор системного
журнала в ХМL-Формате</ТITLE>
<BODY
BGCOLOR="#FFFFFF">
<hЗ>Демонстрация
работы пользовательского обработчика ошибок</hЗ>
В этой программе
осуществляется формирование
пользовательского
системного журнала, который располагается в
каталоге <b>/tmp</b>. Формат системного
журнала - XML+WDDX.<p>
<h4>Первый этап
- генерация журнала</h4>
<?рhр
$sysadmin = "root@1ocalhost"; // адрес администратора системы,
// который получает
сообщение об ошибке в программе
@unlink("/tmp/errorlog.txt"); // прежний журнал не нужен
// Закрываем префиксом @
для предотвращения генерации сообщения
// при отсутствии такого файла
// Вначале открываем
сеанс для записи
error_log("<ERRORLOG>\n".3."/tmp/errorlog.txt");
// И вводим свой собственный обработчик
ошибок
function userErrorHandler ($errno, $errmsg, $filename, $linenum, $vars){
//
Формат отображения времени о журнале в память об
// операционной системе
РАФОС (RT-11)
$dt = date("d-M-Y H:i:s");
// теперь создадим
хэш-массив с кодами и категориями
// сообщений об ошибках
$errortype = array (
1 => "Ошибка".
2 => "Предупреждение",
4 => "Ошибка компилятора",
8 => "Подсказка",
16 => "Ошибка РНР-машины",
32
=> "Предупреждение
РНР-машины",
64 => "Ошибка компилятора",
128 => "Предупреждение компилятора",
256 => "Ошибка
пользователя",
512 => "Предупреждение пользователя",
1024 => "Подсказка
пользователя"
);
//
Сформируем маску отслеживаемых событий
$user_errors = array(E_USER_ERROR,
E_USER_WARNING, E_USER_NOTICE);
// теперь сформируем XML-запись сообщения
об ошибке
// Поскольку
формат прост, мы не будем использовать DOM-модель
// с автоматической
генерацией документа...
$err ="<ERRORENTRY>\n .
$err.="<DATETIME>".$dt."</DATETIME>\n";
$err.="<ERRORNUM>".$errno."</ERRORNUM>\n";
$err.="<ERRORTYPE>".$errortype[$errno]."</ERRORTYPE>\n";
$err.="<ERRORMSG>".$errrmsg."</ERRORMSG>\n";
$err.="<SCRIPTNAME>" $filename."</SCRIPTNAME>\n":
$err.="<SCRIPTLINEMUM>".$linenum."</SCRIPTLINENUM>\n";
if (in_array($errno, $user_errors))
{
// Массив преобразуем с помощьо WODX
$err =
"\t<VARTRACE>";
$err.=
wddx_serialize_value($vars,
"Variables");
$err.= "</VARTRACE>\n";
}
$err.= "</ERRORENTRY>\n\n";
// тестовая
печать в процессе отладки программы
// echo "<pre>$err</pre><p>";
// теперь помешаем
сформированную запись в журнал, и если
// это критическая ошибка, генерируем
сообщение системному
//
администратору
error_log($err, 3,
"/tmp/errorlog.txt");
if
($errno == E_USER_ERROR)
mail($sysadmin,
"Критическая ошибка в программе!".$err);
}
// Функция,
вычисляющая расстояние между двумя векторами.
// которая генерирует
немало сообщений об ошибках
function distance
($vect1, $vect2) {
if
(is_array($vect1) ||
!is_array($vect2)) {
trigger_error("Недопустимый тип
аргументов!",
E_USER_ERROR);
return NULL;
}
if (count($vect1) != count($vect2)) {
trigger_error("Векторы должны иметь
одинаковый размер",
E_USER_ERROR);
return NULL;
}
for
($i=0; $i<count($vect1); $i++) {
$c1 = $vect1[$i];
$c2 = $vect2[$i];
$d = 0.0;
if
(!is_numeric($c1)) {
trigger_error("$i-я координата вектора 1
не
является числом",E_USER_WARMING);
$c1 = 0.0;
}
if (!is_numeric($c2))
{
trigger_error("$i-я координата вектора 2
не
является числом", E_USER_WARNING);
$c2 = 0.0;
}
$d += $c2*$c2 - $c1*$c1.
}
return sqrt($d);
}
// переустанавливаем обработчик ошибок
$old_error_handler = set_error_handler("userErrorHandler");
?>
<ul>
<li>Неопределенная константа
- сформирует сообщение об ошибке
<?
$t = I_AM_NOT_DEFINED;
// теперь создадим несколько
векторов
$а =
array(2.3, "foo");
$b = array(5.5, 4.3, -1.6);
$c = array (1,-3);
?>
<li>Генерируем сообщение об
ошибке при вычислении функции
<?
$t1 = distance($c,$b)."\n";
?>
<li> и еще одно - о неверных
аргументах
<?
$t2 = distance($b,"А я не
массив...")."\n";
?>
<li>А в заключение,
сгенерируем предупреждение...
<?
$t3 = distance($a,$b)."\n";
//
Восстановим системный обработчик
restore_error_handler($old_error_handler);
error_log("</ERRORLOG>\n",3,"/tmp/errorlog.txt");
?>
</ul>
<h4>Восстанавливаем
содержимое журнала и выводим его в виде таблицы</h4>
<?
class
logger {
var $xml_parser;
var $xml_file;
var $html;
var $open_tag;
var $close_tag;
var $wddx_flag; //
флажок обнаружения WDDX-пакета
var $wddx; // поток
WDDX-данных (сборка пакета)
// Конструктор класса
function
logger () {
$this->xml_parser =
"";
$this->xml_file = "";
$this->html = "";
$this->wddx_flag = 0;
$this->wddx = "";
$this->open_tag = array(
// Настраиваем интерпретатор
отдельных
// тегов нашего
заказного формата
"ERRORLOG" => "<TABLE CELLPADDING=5>",
"ERRORENTRY" => "<TR><TD
BGCOLOR=#f2f2f2>".
"DATETIME" =>
"<FONT COLOR=#883800>",
"ERRORNUM" =>
"<TD 8GCOLOR=#f2f2f2>",
"Код ошибки: <FONT COLOR=#000A0C<B> ",
"ERRORTYPE" =>
"Категория ошибки: <FONT
COLOR=#3F3F00>",
"ERRORMSG" =>
'<FONT SIZE=-1><FONT COLOR=#D22323>",
"SCRIPTNAME" => "<р>Файл:
",
"SCRIPTLINENUM" => "строка - <B>",
"VARTRACE" => "<p><FONT COLOR=\"BLUE\">Пepeмeнныe:");
// а здесь - закрывавшие
теги
$this->close_tag = array(
"ERRORLOG" => "</TABLE>\n\n",
"ERRORENTRY" => "</TD></TR>",
"DATETIME" => "</FONT></TD>",
"ERRORNUM" => "</B>",
"ERRORTYPE" => "<br>",
"ERRORHSG" => "</FONT></FONT>",
"SCRIPTNAME" => " ",
"SCRIPTLINENUM => "</B>",
"VARTRACE" =>
"</FONT> ");
}
//
Деструктор класса. В отличие от Си++ и Perl его
// необходимо вызывать
вручную
function destroy() {
xml_parser_free( $this->xml_parser);
}
//Основные функции
введенного нами класса
function concat($str) {
//
дописывает в генерируемый HTML-поток очередную строку
$this-> html .= $str;
}
// Вызывается при начале нового элемента в
документе
function startElement( $parser, $name. $attrs) {
if ($format= $this->open_tag[$name]) {
$this-> html .= $format;
}
if ($name == "VARTRACE") {
$this->wddx_flag = 1;
$this->wddx = "":
} else
if ($this->wddx_fiag == 1) {
$this->wddx .=
"<".$name." "; // открываем тег
// теперь обрабатываем
его аргументы (атрибуты)
while (list ($key, $val) = each($attrs)) {
$this->wddx .= $key."='".$val."'";
}
$this->wddx .= ">";
}
}
}
// Вызывается при окончании обработки
элемента
function endElement($parser, $name ){
global $close_tag;
if ($format= $this->close_tag[$name]){
$this->html .= $format;
}
if ($name == "VARTRACE"){
$this->wddx_flag = 0;
$m = wddx_deseriali2e($this->wddx);
// отладочная печать
// echo "<pre>".$this->wddx."</pre>";
// var_dump($m);
while (list ($key,$val) = each($m)){
//
Добавляем в поток HTML информацию о переменных
$this->html.=
"Аргумент <font
color=\"black\">";
$this->html.= "<b>".$key."</b></font>: ";
if (is_array($val)){
$this->html.= implode(',',$val);
}
else{
$this->html.= $val;
}
$this->html.= " ";
}
}
if ($this->wddx_flag == 1){
$this->wddx.="</".$name.">";
}
}
// Обработчик символьных данных СDАТА
function characterData ($parser, $data ) {
// во избежание недомолвок
if
($this->wddx_flag == 1) {
this->wddx.= $data;
}
else{
$this->html.= $data;
}
}
// Разбор файла
function
parse() {
$this->xml_parser=
xml_parser_create();
xml_set_object($this->xml_parser, &$this);
//
обратите внимание на нивелирование регистров тегов
// что позволяет при
лобом раскладе установить соответствие
// их с записями $mар_аrrау
xml_parser_set_option($this->xml_parser,
XML_OPTION_CASE_FOLDING, false );
xml_set_element_handler($this->xml_parser,
"startElement",
"endElement");
xml_set_character_data_handler($this->xml_parser,"characterData");
if (!($fp = fopen($this->xml_file,"r"))) {
die("He могу открыть
входной файл XML");
}
while ($data =
fread($fp, 4096)) {
if
(!xml_parse($this->xml_parser, $data, feof($fp))) {
die(sprintf("Ошибка в XML файле : %s на
строке %d",
xml_error_string(
xml_get_error_code(
$this->xml_parser )),
хml_get_current_line_number($this->xml_parser)));
}
}
}
$log =
new_logger();
$log->xml_file
="/tmp/errorlog.txt";
$log->parse();
print ($log->html);
$log->destroy();
?>
|