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




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

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

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

<?php // Полная загрузка сервисных книжек, создан 2026-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 не будет опубликован. Обязательные поля помечены *