При обмене данными с внешними системами, особенно при загрузке наименований товаров или описаний с веб-сайтов, разработчики часто сталкиваются с ошибкой: «Текст XML содержит недопустимый символ». Для этой задачи есть универсальный перенос данных между базами XML. Эта проблема обусловлена строгими требованиями стандарта XML 1.0, который используется в платформе 1С для чтения и записи XML-документов. В данной статье мы подробно разберем, почему возникает эта ошибка и какими способами можно очистить текстовые данные, чтобы обеспечить их корректную выгрузку и загрузку.
Для начала проанализируем ситуацию: почему 1С отказывается записывать, казалось бы, обычный текст? Согласно спецификации XML 1.0, в документе запрещено использование большинства управляющих символов (Control Characters) из диапазона кодов ASCII от 0 до 31. Исключение составляют только три символа: горизонтальная табуляция (код 9), перевод строки (код 10) и возврат каретки (код 13).
Все остальные символы в диапазонах 0-8, 11-12 и 14-31 считаются недопустимыми. Если парсер 1С встречает их в тексте при формировании файла через ЗаписьXML, работа прерывается с ошибкой. Часто такие символы попадают в базу данных при копировании текста из Excel, Word или при парсинге сайтов, где используются специфические символы форматирования или «мусорные» байты. В этом поможет выгрузка номенклатуры в XML для маркетплейсов.
Если ваша конфигурация построена на базе БСП (что справедливо для большинства современных решений, таких как ERP, УТ 11, БП 3.0), то самый простой и эффективный способ — воспользоваться готовым методом общего модуля. Рассмотрим функцию ЗаменитьНедопустимыеСимволыXML(), которая находится в модуле ОбщегоНазначенияКлиентСервер.
Преимущество этого метода в том, что он написан профессионалами, учитывает все нюансы платформы и работает максимально быстро. Рассмотрим пример использования:
// Очистка строки перед записью в XML
ТекстОписания = "Ваш текст с сайта...";
БезопасныйТекст = ОбщегоНазначенияКлиентСервер.ЗаменитьНедопустимыеСимволыXML(ТекстОписания, " ");
// Второй параметр — это символ, на который будут заменены недопустимые символы (по умолчанию пробел)
Этот метод рекомендуется как основной для всех разработчиков, так как он минимизирует вероятность ошибок при ручном написании кода очистки.
Начиная с версии 8.3.10, в платформе 1С появилась встроенная функция НайтиНедопустимыеСимволыXML(). Для её отладки пригодится инструментарий разработчика с консолью кода. Она позволяет быстро найти позицию первого «запрещенного» знака в строке. Выясним причину, по которой ручное удаление в цикле через Лев() и Сред() может быть неэффективным, и как сделать это правильно.
Посмотрим на пример функции очистки, которую можно внедрить в свой проект:
Функция УдалитьНедопустимыеСимволыXML(Знач ВходнаяСтрока) Экспорт
Позиция = НайтиНедопустимыеСимволыXML(ВходнаяСтрока);
Пока Позиция <> 0 Цикл
// Удаляем один символ и ищем следующий
ВходнаяСтрока = Лев(ВходнаяСтрока, Позиция - 1) + Сред(ВходнаяСтрока, Позиция + 1);
Позиция = НайтиНедопустимыеСимволыXML(ВходнаяСтрока);
КонецЦикла;
Возврат ВходнаяСтрока;
КонецФункции
Важный нюанс производительности: если вы работаете с очень большими текстами (мегабайты данных), создание новой строки на каждой итерации цикла (через оператор +) существенно замедлит работу. В таких случаях лучше использовать СтрРазделить и СтрСоединить или предварительно проверять наличие недопустимых символов перед обработкой.
Иногда требуется более тонкая настройка фильтрации. Рассмотрим программный способ обхода строки, где мы проверяем код каждого символа. Это полезно, если вы хотите не просто удалить символ, а выполнить логирование или специфическую замену.
Проанализируем диапазоны запрещенных кодов:
Пример реализации на языке 1С:
Функция ОчиститьСтрокуПоКодам(Текст)
Результат = "";
Для Позиция = 1 По СтрДлина(Текст) Цикл
Код = КодСимвола(Текст, Позиция);
// Проверка по стандарту XML 1.0
Если (Код < 9)
Или (Код > 10 И Код < 13)
Или (Код > 13 И Код < 32) Тогда
// Пропускаем символ (удаляем)
Продолжить;
Иначе
Результат = Результат + Символ(Код);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Для опытных разработчиков наиболее быстрым и лаконичным способом является использование регулярных выражений через COM-объект VBScript.RegExp. Этот метод позволяет очистить всю строку за один вызов, не создавая циклов в коде 1С.
Рассмотрим, как это реализовать:
Функция ОчиститьЧерезRegExp(Текст)
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.Global = Истина;
RegExp.IgnoreCase = Истина;
RegExp.MultiLine = Истина;
// Регулярное выражение для поиска всех запрещенных символов XML 1.0
RegExp.Pattern = "[^\x09\x0A\x0D\x20-\xD7FF\xE000-\xFFFD\x10000-\x10FFFF]";
Возврат RegExp.Replace(Текст, "");
КонецФункции
Использование RegExp особенно актуально при работе с Emoji и сложными символами Unicode, так как позволяет гибко задавать разрешенные и запрещенные диапазоны.
Некоторые программисты ошибочно полагают, что использование функции XMLСтрока() решит проблему. Разберем этот момент подробнее. Функция XMLСтрока() предназначена для преобразования типизированных данных (чисел, дат, ссылок) в строковое представление XML. Если вы передадите в неё строку, которая уже содержит символ с кодом 1, функция **не удалит** его. Она лишь экранирует стандартные спецсимволы разметки, такие как <, > и &. Очистка от невалидных управляющих кодов — это задача, которую нужно решать до вызова функций сериализации.
Чтобы раз и навсегда избавиться от подобных ошибок, рекомендуем придерживаться следующих правил:
ОбщегоНазначенияКлиентСервер.ЗаменитьНедопустимыеСимволыXML(), если библиотека подключена к вашей конфигурации.Таким образом, мы рассмотрели все основные инструменты для борьбы с недопустимыми символами XML в 1С. Выбор конкретного метода зависит от архитектуры вашей базы и требований к производительности, но наиболее надежным остается путь использования стандартных средств БСП.