Парсинг XML на PHP с сохранением в MYSQL
ЗАДАЧА
Требуется написать функцию (одно входное значение типа int, выходное значение - код завершения типа int), которая:
1. проверяет актуальность данных а таблице (срок актуальности указывается константой)
если данные данные не актуально, то
1. по указанному параметру запрашивает по http (без авторизации) новые xml-данные.
2. парсит xml и сохраняет в единственную mysql-таблицу, удалив предыдущие данные.
XML имеет практически линейную структуру: группы по 14 обязательных тегов без атрибутов.
Специфика: функция должна работать в многопользовательской среде, а объем данных значительный (в XML около 10 000 групп тегов) при медленном отклике xml-шлюза. В связи с этим алгоритм услажнен семафором.
Далее описание таблиц, структуры XML и алгоритм, в котором подробно описана работа семафора.
ОПИСАНИЕ СТРУКТУРЫ ТАБЛИЦ MYSQL
1. LISTSPO_DATA
Таблица для хранения данных из XML
Поля:
spolist_id - это входной параметр
14 полей из xml c идентичными именами
Первичного ключа нет
Индексы: spolist_id,pt_hdname,pt_hdstars
2. LISTSPO
Таблица для хранения справочника скаченных XML-файлов
Поля:
spolist_id int primary key
dt_lastupdate timestamp
status enum(ready,preprocessing,processing)
описание значений:
ready - данные доступны
preprocessing - готовится обновление данных, но усторевшие данные еще доступны
processing - идет обновление данных, данные недоступны
3. LISTSPO_LOG
Таблица для хранения истории изменения справочника скаченных XML-файлов
Поля:
spolist_id int index
dt_lastupdate timestamp
status enum(ready, preprocessing,processing)
NOTE: Для таблиц listspo,listspo_log все запросы дублируются обязательно в обе таблицы и имеют вид:
REPLACE INTO * SET listspo_id=$listspo_id, status='$status'
ОБРАЗЕЦ XML
-
-
2207
Abri (Praha 2)
3*
Прага
Single
1
Standard
1
Adult
0
Завтрак буфет
2010-11-02T00:00:00+03:00
9
491
-
......
АЛГОРИТМ С СЕМАФОРОМ (в приведенных sql-запросах могут быть не точности, они даны для наглядности)
0. вызов функции listspo($listspo_id)
const LIMIT_READY=600
const LIMIT_PROCESSING=30
const LIMIT_ERROR=60
const LIMIT_INSERT_CORTEGE=1000
const SLEEP_TIME=1
const URL_XML='http://site.ru/xml?id='
1. выполнить запрос
SELECT UNIX_TIMESTAMP()-UNIX_TIMESTAMP(dt_lastupdate) AS duration,status FROM listspo WHERE spolist_id=$spolist_id
2. если status='ready' AND duration
-- данные еще актуальны, обновление не требуется
3. если status='preprocessing' AND duration
-- готовится обновление данных, но еще можно воспользоваться устарвешими данными
4. если status='processing' AND duration
-- критическое обновление данных, данные недоступны, требуется ожидание завершения обновления
5. если status='ready' AND duration>=LIMIT_READY, то выполнить запрос и начать обновление (п.8)
-- требуется обновление данных
REPLACE INTO * SET listspo_id=$listspo_id, status='preprocessing'
6. если status='preprocessing' AND duration>=LIMIT_PROCESSING, то выполнить запрос и начать обновление (п.8)
-- таймаут обновления, обновление следует начать с начала
REPLACE INTO * SET listspo_id=$listspo_id, status='preprocessing'
7. если status='processing' AND duration>=LIMIT_PROCESSING, то выполнить запрос и начать обновление (п.8)
-- таймаут обновления, обновление следует начать с начала, данные недоступны
REPLACE INTO * SET listspo_id=$listspo_id, status='processing'
9. загрузить данные с адреса URL_XML.$listspo_id
10. если загрузка завершилась ошибкой, то функция завершает работу (return 2)
9. распарсить данные и сформировать sql-запросы на вставку: INSERT с кортежами не более LIMIT_INSERT_CORTEGE штук
10. выполнить запрос
REPLACE INTO * SET listspo_id=$listspo_id, status='processing'
11. удалить старые данные
DELETE FROM listspo_data WHERE listspo_id=$listspo_id
12. выполнить sql-запросы на вставку
13. выполнить запрос
REPLACE INTO * SET listspo_id=$listspo_id, status='ready'
14. функция завершает работу (return 0)
NOTE: При любой ошибке работы с mysql функция завершает работу (return 3)
Список возвращаемых функцией кодов ошибок:
1. осуществляется обновление и данные для использования недоступны
2. http-ошибка загрузки новых данных
3. ошибка базы данных
Требования к коду:
1. константы должны быть определены вначале файла и прокомментированы
2. названия таблиц определить константами
3. обязательно комментирование основных операторов
4. все пути к локальным файлам нужно указывать через dirname(__FILE__) - если такие пути потребуются
5. строгих лимитов по использованию памяти и времени выполнения нет
Кроме реализации алгоритма от исполнителя требуется хороший стиль.