Парсинг xml с выгрузкой в БД. Часть 1.

Опубликовано Опубликовано в рубрике PHP, XML

Сегодня речь пойдёт о развивающейся технологии XML, которая захватывает всё большую и большую аудиторию.

Итак, постановка задачи.
Дано: выгрузка отчёта системы в формате XML с жёсткой структурой.
Требуется: обработать (читаем — распарсить) этот документ, грамотно выгрузить его в БД, затем организовать вывод полученной базы в формы с возможностью фильтрации.

В этой заметке я рассмотрю проблему правильного парсинга документа.

С синтаксисом и концепцией языка XML Вы сможете ознакомиться здесь.

Начнем.

Вид документа на входе имеет примерно следующую структуру

<?xml version=’1.0′ encoding=’UTF-8′?>
<PNRS>
<PNR>
<Common>
<id>160303</id>
<Type>FLIGHTS
</Type>
<Service>GALILEO
</Service>
<Locator>
</Locator>
<BeginDateTime>2011.11.03-21:35
</BeginDateTime>
<EndDateTime>2011.11.03-23:10
</EndDateTime>
<TotalPrice>
<Amount>7060
</Amount>
<CurrencyCode>RUB
</CurrencyCode>
</TotalPrice>
<UserId>10878
</UserId>
<UserLogin>
</UserLogin>
<GroupId>10876
</GroupId>
<UserStatus>Группа
</UserStatus>
<DateCreate>2011.11.01-14:38
</DateCreate>
</Common>
</PNR>
</PNRS>

Для парсинга используем всеми любимый язык PHP. В его распоряжении есть функции обработки xml-документов. Начнем работу.

function startElement($parser, $name, $attrs) {
global $depth;
echo str_repeat("-", $depth * 3); // отступы
echo "Элемент: $name
"; // имя элемента
$depth++; // увеличиваем глубину, чтобы браузер показал отступы

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

Функция startElement определяет факт вхождения элемента структуры и говорит системе, что делать с открывающимся тегом. На вход функции подаются три переменные.
Внутри функции мы используем глобальную переменную $depth, которая отвечает за построение древовидной структуры вывода (отступов, говоря по-русски =) ).
После её объявления мы выводим отступ и значение тэга, а также увеличиваем отступ для последующих вложенных тегов при их наличии.

Если у тега есть аттрибуты, то идущий следом цикл foreach поможет вывести их значения также в древовидной структуре.

Следующая функция отвечает за идентификацию закрытия тэга и выглядит следующим образом:

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

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

Тут всё просто. Нам необходимо уменьшить отступ для поддержания структуры.

Дальше нам надо каким-то образом вывести содержимое тэгов. Для этого будет использоваться вот такая функция:
function stringElement($parser, $str) {
if (strlen(trim($str)) > 0) 
	{
	global $depth;

echo str_repeat("-", $depth * 3); // отступ
echo 'Значение : '.$str.'
'; // выводим строку

Что ж, функции мы описали. Теперь надо всё организовать. Для этого обозначим две переменные:

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

Первая отвечает за начало построения дерева, а во второй мы обозначаем подключение нашего xml-файла. Совсем несложно сделать подключение оного динамически при помощи простых форм и POST-передачи.

Теперь используем несколько встроенных php-функций.

$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, stringElement);
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false);

Первой мы обозначаем сам парсер, вторая говорит ему о том, какие функции будут производить обработку кода, в третьей программе передаётся содержимое тэгов, ну а четвёртая выводит всё нормальным «некапслочным» шрифтом (изначально регистр вывода установлен верхний).

Теперь начинается непосредственно парсинг.

if (!($fp = fopen($file, "r"))) {
die("could not open XML input");
}
while ($data = fgets($fp)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
echo "
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);

Теперь можно смело запустить нашу программку. Итогом первой части работы над поставленной задачей будет следующий вывод:
-Элемент: PNRS
—Элемент: PNR
——Элемент: Common
———Элемент: id
————Значение: 160303
———Элемент: Type
————Значение: FLIGHTS
———Элемент: Service
————Значение: GALILEO
———Элемент: Locator
————Элемент: BeginDateTime
—————Значение: 2011.11.03-21:35
————Элемент: EndDateTime
—————Значение: 2011.11.03-23:10
————Элемент: TotalPrice
—————Элемент: Amount
——————Значение: 7060
—————Элемент: CurrencyCode
——————Значение: RUB
—————Элемент: UserId
——————Значение: 10878
—————Элемент: UserLogin
——————Элемент: GroupId
———————Значение: 10876
——————Элемент: UserStatus
———————Значение: Группа
——————Элемент: DateCreate
———————Значение: 2011.11.01-14:38

А в следующей части статьи мы научим нашу программу писать необходимые данные в Базу Данных.

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

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