Ошибка преобразования данных XDTO: Текст XML содержит недопустимый символ




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

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

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

<?php // Полная загрузка сервисных книжек, создан 2025-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='\

25 Comments

  1. CagoBHuK

    Лучший вариант — воспользоваться этим: http://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1­%8B%D0%B5_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D­1%8F

    Reply
  2. StepByStep

    (1) CagoBHuK,

    На мой взгляд — воспользоваться типовым вариантом предложенным в статье.

    Reply
  3. Yashazz

    (1) Соглашусь. Для больших объёмов регулярные выражения быстрее будут, чем посимвольный обход.

    Reply
  4. CagoBHuK

    (2) Видимо, Вы не работали с большими объемами данных. При файлах более 100 мегабайт Ваша обработка встанет колом.

    Reply
  5. StepByStep

    (4) CagoBHuK,

    Да. Если база большая и «шерстить» все — это медленно, но верно.

    Издержки посимвольного обхода.

    Reply
  6. CagoBHuK

    (5) А с каких пор регулярные выражения — это неверно?

    Reply
  7. StepByStep

    (6) CagoBHuK,

    Регулярные выражения не рассматривал, надо попробовать.

    Reply
  8. StepByStep

    (6) CagoBHuK,

    СПАСИБО. ТОЖЕ ВЕРНО!

    Reply
  9. CagoBHuK

    (8) Не за что. Приятно, когда люди прислушиваются к твоим словам.

    Reply
  10. StepByStep

    (9) CagoBHuK,

    Еще раз спасибо. Добавил функцию на RegExp.

    Reply
  11. OrsoBear

    У меня такие ошибки выпадали после импорта из 1С 7.7

    Как правило, в процессе работы вываливались конкретные справочники и элементы, в которых ошибка.

    И вываливалось при поиске или отборах. Если тупо колесиком до нужного пункта докрутить, то не вываливалось.

    Открывал карточку, видел в поле среди букв какой-нибудь спецсимвол. Ручками исправлял, и удалял файл индексации.

    После этого вопрос решался.

    Тестирования и прочие стандартные методы нивкакую ошибки не находили.

    Reply
  12. ArikiteSun

    Спабсибо! Полезная информация!

    Reply
  13. StepByStep

    (11) OrsoBear,

    СПАСИБО.

    Да, в семерке при экспорте-импорте из ТиС в Бухгалтерию неоднократно встречалась проблема с недопустимыми символами XML. И тоже ручками исправлял.

    На 8-ке решил, что надо по-другому …

    Reply
  14. kiruha

    Вопрос — для вебсервисов, если передаются наименования — нужно ли их проверять на недопустимые символы ?

    И как со знаками «<«, «>» ?

    Reply
  15. StepByStep

    (14) kiruha,

    По опыту работы с 1С 7.7, а теперь и 1С 8.Х, я пришел к такому выводу:

    Все, что приходит из внешнего источника данных в рабочую базу обязательно должно проходить проверку.

    В данном случае речь идет о чистке строковых значений для реквизитов 1С.

    Символы «<» (меньше) или «>» (больше) — в строковом реквизите это вполне допустимый символ, если это не запрещено в конкретной конфигурации.

    Reply
  16. kiruha

    Спасибо большое — буду проверять.

    Знак «>» в xml знак тэга. Я так понял — не влияет при экспорте ?

    Reply
  17. kraynev-navi

    «Если звезды зажигают, значит это кому-нибудь нужно»

    А что если недопустимые символы очень даже нужны? А мы их просто берем и удаляем…

    Столкнулись с ситуацией при обмене. Строковый реквизит стандартным средством СоздатьЗаписьСообщения выдает ошибку из-за символов с кодом 01. В базе таковых 2000+ записей. Можно, конечно, все это просмотреть и принять решение по каждому. Но дальше же снова будут появляться такие документы. Нет уверенности, что удаление будет показано всем.

    Проблемы можно было бы избежать, кодируй 1С значение банальным base64. Но нет, версия 8.2 лепит как есть.

    Кто и как ходил путем «неудаления»?

    Reply
  18. kraynev-navi

    (16) kiruha, вроде как нормально конвертирует, ошибок нет

    Данные реквизита:

    выапвыапвы<st yle>[]{}

    Сообщение обмена:

    <ДругоеНазвание>выапвыапвы<style>[]{}</ДругоеНазвание>
    Reply
  19. nadinvital

    Спасибо,очень полезная штука, а главное актуальная

    Reply
  20. dima_kystym

    что то у меня не запускается эта обработка, под тонким вот такое сообщаение и все., а под толстым вообще не открывается. что может быть. Управление торговлей, редакция 11.1 (11.1.2.6)

    § | §§ » | ☺☻♥♦♣♠•◘○◙♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !

    ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz

    АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщ­ъыьэюя

    ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω

    0123456789

    ~`!@#$%#k8SjZc9Dxk&*(){}[]_-=+|/*:;.<>?,№ !

    ‘ | © | ® | µ | «» | ¤¢€£¥ | § | ½¼¾ | ¹²³ | °±×÷؃§ µ

    § | §§ » | § ! ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщ­ъыьэюя ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω 0123456789 ~`!@#$%#k8SjZc9Dxk&*(){}[]_-=+|/*:;.<>?,№ ! ‘ | © | ® | µ | «» | ¤¢€£¥ | § | ½¼¾ | ¹²³ | °±×÷؃§ µ

    Reply
  21. StepByStep

    (20) dima_kystym,

    Пример практического использования можно увидеть здесь: http://infostart.ru/public/120961/

    Reply
  22. a_E

    Спасибо за код помогло.

    Reply
  23. igo1

    Спасибо помогло

    Reply
  24. kote

    .

    Reply
  25. SlaSla

    Подскажите по 7.7 есть аналогичный вариант?

    Reply

Leave a Comment

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