Проверка по схеме XML-файла (валидация по XSD)




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

27 Comments

  1. Yashazz

    Абсолютно бесполезная вещь.

    Открою страшный секрет: валидность с точки зрения утилит msxml и с точки зрения 1С — совершенно разные вещи. Будьте готовы к тому, что файл, признанный валидным, не сработает, вызовет вылетание платформы, просто никак не прочитается и прочая. Аналогично, валидность xsd-схемы как таковой для большинства нормальных приложений и для 1С — разная. Многие схемы просто не грузятся, причём 1С ничего вообще не сообщает — тихо игнорит и всё. Фабрика может не скушать xsd, xml может «не подойти», хоть его 100% подгоняй, и прочее.

    Например, полезнейшая штука построения xsd по имеющемуся файлу xml выдаёт схему, которую легко читают и понимают все, кроме 1С.

    Это я к чему — имея дело с xml-механикой 1С, не полагайтесь на НЕ-1Сные фичи.

    Reply
  2. andrewks

    (1) Yashazz, собственно, я и не позиционировал обработку как проверялку для закачки файлов парсером 1С.

    обработка делает ровно то, что и заявлено — проверяет файл на соответствие стандарту XML и приложенной схеме XSD.

    лично я очень часто использую этот функционал при:

    1. написании и отладки кода по формированию/выгрузке xml-файлов для сторонних приложений/сервисов, когда структура оговорена схемой

    2. после отладки — внедряю в код для выгрузки автоматическую проверку выгруженного файла по схеме. позволяет сэкономить время, укорачивая цепочку — многие ошибки сразу показываются при выгрузке, а не после закачки на какой-нибудь портал.

    P.S. открою секрет — абсолютно бесполезных вещей не бывает! бывают бесполезные для кого-то

    Reply
  3. andrewks

    (1) Yashazz, поскольку форум проглючил, и сообщение не сохранилось, повторю кратко:

    а сторонний функционал (msxml) был выбран именно потому, что я довольно пообщался с функционалом 1С касательно xml/xsd, чтобы опасаться его использовать в этом вопросе

    Reply
  4. Yashazz

    (2),(3) А, ну «тады да». Тогда вопросов больше не имею. Если 1С-ные грабли известны, и сторонний функционал взят нарочно, то, может, это и правда best practice.

    Reply
  5. CagoBHuK

    Всем: пользуйтесь Altova XML Spy.

    Reply
  6. andrewks

    (5) CagoBHuK, ничего, что он платный?

    Reply
  7. CagoBHuK

    (6) При желании можно найти и бесплатный аналог, и лекарство от жадности. А вообще нормальный программист найдет денег для того, чтобы купить себе хороший инструмент.

    Reply
  8. andrewks

    (7) CagoBHuK,

    А вообще нормальный программист найдет денег для того, чтобы купить себе хороший инструмент.

    нормальный программист может также найти время на написание инструмента самому, не так ли?

    Reply
  9. CagoBHuK

    (8) Да, но сначала он задастся следующими вопросами:

    • Зачем изобретать велосипед?
    • Будет ли потраченное время стоить тех денег, которые придется заплатить за уже существующий инструмент?
    Reply
  10. andrewks

    (9) CagoBHuK, я оценил, и решил, что быстрее и дешевле написать самому обработочку, юзающую msxml, и пользоваться. тем более, что больше от альтовы мне ничего не надо (кроме валидации). и даже решил поделиться с общественностью

    раз в винде заложен данный функционал — почему бы им не воспользоваться? ну, а у кого есть лишние деньги — пусть покупают хоть альтову, хоть другое ПО — я ж не против.

    только не пойму, какой смысл агитировать за покупку коммерческого ПО в камментах к бесплатному продукту

    Reply
  11. CagoBHuK

    (10) Я никого ни к чему не агитирую. Я специально сделал приписку, что при желании можно найти бесплатный продукт.

    Reply
  12. Ёпрст

    Эээ.. а в штатном снеговике разве нет валидации по схеме ?

    ..

    Reply
  13. andrewks

    (12) Ёпрст, лично у меня не получилось это сделать со штатным функционалом. если есть реально рабочий пример — милости просим

    Reply
  14. Ёпрст

    Я не проверял, мне лень, как то валидацию, в своих поделках повыкидывал, за ненадобностью.

    Reply
  15. sikuda

    Да чего-то Microsoft Validator это конечно лучше, чем от 1С но тоже есть непонятки. Altova тоже советую…

    Reply
  16. Yury1001

    Спасибо, огромное, искал аж с ног сбился — декларант-алко не запускается, а файлы перед отправкой проверить хочется.

    +1

    Reply
  17. Широкий

    Пытался проверить файл по схеме ЕГАИС:

    ==================================================================

    16.12.2015 14:14:18: Начата проверка по схеме файла: C:111.xml

    Не удалось подключить схему: C:ЕГАИСxsdWB_DOC_SINGLE_01.xsd

    16.12.2015 14:14:18: Проверка завершена

    ============================================================­======
    Reply
  18. nikulin76

    На схемы от ЦБ тоже ругается

    … Не удалось подключить схему: …

    Reply
  19. RomanUzmov

    (19) nikulin76, Аналогичная ситуация

    Reply
  20. andrewks

    (19) nikulin76, попробуйте такой вариант

    Reply
  21. EvgKo

    Добрый день!

    При валидации ХМЛ-файла с помощью данной обработки выдается сообщение:

    «Обнаружена ошибка:

    Смещение = 612, строка = 8, позиция = 17, код ошибки: -1072898035

    Описание ошибки: Элемент »{http://fsrar.ru/WEGAIS/TTNSingle_v2}Identity» используется, но не был объявлен в DTD и схеме.»

    В самой схеме «TTNSingle_v2» объявление «Identity» есть. Подскажите, в чем может быть проблема?

    Reply
  22. Rudakov_D

    У меня тоже выдала ошибку

    28.11.2016 16:39:42: Начата проверка по схеме файла: D:valv8_D76D_7b.xml

    Не удалось подключить схему: D:valTTNSingle_v2.XSD

    28.11.2016 16:39:43: Проверка завершена

    Reply
  23. NAlex

    Собственно, опять же ошибка:

    ============================================================­======

    18.01.2017 17:39:26: Начата проверка по схеме файла: C:UsersabcDesktopd13381f-79d8-430f-953d-fd4608fbc97e.xml

    Не удалось подключить схему: W:for_filesPledgeRegistry.xsd

    18.01.2017 17:42:41: Проверка завершена

    ============================================================­======

    несмотря на то, что Altova XMLSpy 2011 Enterprise Edition успешно валидировала этой файл Xml этой схеме Xsd.

    В чем может быть проблема?

    Reply
  24. kauksi

    работающий вариант: кусок кода процедуры Проверка по схеме клиент

    //Прочитаем схему
    Попытка
    xmldoc=Новый COMОбъект(«MSXML2.DOMDocument.6.0»);
    Исключение
    ВывестиСообщение(«Не удалось создать объект DOM1Document (возможно, не установлен MSXML 6)»,2);
    Схема=Неопределено;
    Возврат РезПроверки;
    КонецПопытки;
    
    xmldoc.async = false;
    xmldoc.load(ИмяФайлаСхемы);
    
    Если (xmldoc.parseError.errorCode<>0) Тогда
    // ошибки при проверке правильности
    ВывестиСообщение(«При проверке по схеме выявлены ошибки!»,Куда,Форматировать);
    Если ВыводитьВсеОшибки Тогда
    Для каждого parseError из xmldoc.parseError.AllErrors  Цикл
    ВывестиОшибкуРазбораХМЛ(parseError.reason,Куда,Форматировать);
    КонецЦикла;
    Иначе
    ВывестиОшибкуРазбораХМЛ(xmldoc.parseError.reason,Куда,Форматировать);
    КонецЕсли;
    КонецЕсли;
    
    
    // Подключим ее
    Попытка
    Схема=Новый COMОбъект(«MSXML2.XMLSchemaCache.6.0»);
    Исключение
    ВывестиСообщение(«Не удалось создать объект XMLSchemaCache (возможно, не установлен MSXML 6)»,2);
    Возврат РезПроверки;
    КонецПопытки;
    
    Попытка
    Схема.addCollection(xmldoc.namespaces);
    //Схема.add(,ИмяФайлаСхемы);
    Исключение
    ВывестиСообщение(«Не удалось подключить схему: «+ИмяФайлаСхемы,2);
    Схема=Неопределено;
    Возврат РезПроверки;
    КонецПопытки;

    Показать

    Reply
  25. kauksi

    однако выводимая ошибка не очень информативна

    Обнаружена ошибка:

    Смещение = 215, строка = 2, позиция = 193, код ошибки: -1072897676

    Описание ошибки: Значение не может быть пустым

    понятно что какой то элемент не заполнен, а вот какой не говорит, собака

    Reply
  26. anton448

    Добрый день, andrewks

    Помогите пжл. разобраться в такой проблеме.

    Скачал последнюю вашу обработку с рабочим кодом, файл проверяется по схеме, но при этом всегда сообщается, что «Файл успешно прошёл проверку по схеме!», хотя я файл специально «ломаю», чтобы получить ошибку при проверке….

    Т.е.в коде система почему то не проваливается в условие

    Если (ДОМ.parseError.errorCode<>0) Тогда
    // ошибки при проверке правильности
    ВывестиСообщение(«При проверке по схеме выявлены ошибки!»,Куда,Форматировать);
    Если ВыводитьВсеОшибки Тогда
    Для каждого parseError из ДОМ.parseError.AllErrors  Цикл
    ВывестиОшибкуРазбораХМЛ(parseError,Куда,Форматировать);
    КонецЦикла;
    Иначе
    ВывестиОшибкуРазбораХМЛ(ДОМ.parseError,Куда,Форматировать);
    КонецЕсли;
    Иначе
    ВывестиСообщение(«Файл успешно прошёл проверку по схеме!»,Куда,Форматировать);
    РезПроверки=Истина;
    КонецЕсли;

    Показать

    Получается, что «ДОМ.parseError.errorCode» всегда равно 0, хотя ошибки есть 100%

    Во вложении сама обработка, файл, который нужно проверить и схема (для наглядности)

    Спасибо.

    Reply
  27. tezdal

    18.10.2018 17:43:17: Начата проверка по схеме файла: D:debugR2_3019021828_098_18102018_7b85db23-df15-494d-b8b2-819f1e829034.xml

    Не удалось подключить схему: D:12-o.xsd

    Описание ошибки: {ВнешняяОбработка.ВалидацияXML.Форма.Форма.Форма(171)}: Ошибка при вызове метода контекста (add): Типы не совпадают (1)

    18.10.2018 17:43:19: Проверка завершена

    Схема.add(«»,ИмяФайлаСхемы); решило эту проблему.

    Reply

Leave a Comment

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