При работе с электронными счетами-фактурами (ЭСЧФ) в среде 1С 7.7 пользователи часто сталкиваются с ситуацией, когда выгрузка документа в формат XML завершается фатальной ошибкой. Примечательно, что проблема может возникать избирательно: для одного контрагента файл формируется корректно, а для другого — система выдает ошибку парсера. В данной статье мы подробно разберем, почему это происходит, как найти "скрытых врагов" в строках данных и как модифицировать программный код для автоматического исправления подобных ситуаций.
Основная причина кроется в самой природе формата XML. Стандарт XML 1.0 накладывает жесткие ограничения на символы, которые могут содержаться внутри текстовых узлов. Если в адресе, наименовании или ином реквизите контрагента встречаются определенные знаки, парсер (программа, читающая файл) воспринимает их как элементы разметки, что приводит к нарушению структуры документа.
Проанализируем пять "запретных" символов, которые всегда должны заменяться на специальные последовательности (сущности):
& (амперсанд) — должен заменяться на &< (меньше) — должен заменяться на <> (больше) — должен заменяться на >" (двойная кавычка) — должен заменяться на "' (одинарная кавычка) — должен заменяться на 'Если в карточке контрагента, например, указан адрес «ООО "Ромашка" & Ко», то без специальной обработки XML-файл будет содержать кавычки и амперсанд в чистом виде, что и вызовет ошибку при попытке загрузки на портал или открытии парсером.
Для решения проблемы нам необходимо создать функцию, которая будет "прогонять" через себя каждую строку, записываемую в XML. Рассмотрим пример реализации такой функции на языке 1С 7.7. Обратите внимание на критически важный момент: замена амперсанда должна производиться в первую очередь.
Проанализируем, почему порядок важен. Если мы сначала заменим кавычку на ", а затем заменим все символы & на &, то наша кавычка превратится в &quot;, что является грубой ошибкой разметки. Поэтому сначала экранируем амперсанд, а затем всё остальное.
Функция ПодготовитьСтрокуДляXML(Знач Стр)
Стр = СокрЛП(Стр);
// 1. Амперсанд заменяем ПЕРВЫМ
Стр = СтрЗаменить(Стр, Симв(38), "&");
// 2. Остальные спецсимволы
Стр = СтрЗаменить(Стр, "<", "<");
Стр = СтрЗаменить(Стр, ">", ">");
Стр = СтрЗаменить(Стр, Симв(34), """);
Стр = СтрЗаменить(Стр, "'", "'");
Возврат Стр;
КонецФункции
Иногда визуально адрес контрагента выглядит абсолютно корректно: нет ни кавычек, ни лишних знаков. Однако ошибка все равно сохраняется. Это происходит из-за попадания в строку непечатных символов ASCII при копировании данных из Excel, PDF-файлов или электронных писем. К таким символам относятся знаки управления с кодами от 0 до 31 (кроме табуляции и перевода строки).
Выясним, какие символы чаще всего "ломают" выгрузку ЭСЧФ:
Дополним нашу функцию блоком очистки от нежелательных кодов:
Функция ОчиститьСтрокуОтМусора(СтрокаДанных)
Результат = "";
Для к = 1 По СтрДлина(СтрокаДанных) Цикл
КодСимвола = КодСимв(Сред(СтрокаДанных, к, 1));
// Оставляем только допустимые символы
// (коды < 32 являются управляющими, их лучше исключить, кроме 9, 10, 13)
Если (КодСимвола < 32) И (Найти("9,10,13", Строка(КодСимвола)) = 0) Тогда
Продолжить;
ИначеЕсли КодСимвола = 160 Тогда // Заменяем неразрывный пробел
Результат = Результат + " ";
ИначеЕсли КодСимвола = 173 Тогда // Игнорируем мягкий перенос
Продолжить;
Иначе
Результат = Результат + Сред(СтрокаДанных, к, 1);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Вместо того чтобы вручную заниматься заменой каждого символа через СтрЗаменить, мы можем применить более современный и надежный подход — использование объекта MSXML2.DOMDocument. В 1С 7.7 этот объект доступен через механизм OLE. Основное преимущество заключается в том, что при записи значения в свойство text узла, объект самостоятельно выполнит все необходимые преобразования (экранирование).
Посмотрим на пример создания узла с автоматическим экранированием:
// Создаем объект DOMDocument
xmlDoc = СоздатьОбъект("MSXML2.DOMDocument");
// Создаем элемент (например, Адрес)
НовыйУзел = xmlDoc.createElement("address");
// Присваиваем значение напрямую - объект сам заменит <, >, & и т.д.
НовыйУзел.text = "ООО 'Альфа' & Омега <Беларусь>";
// Теперь НовыйУзел.xml будет содержать: <address>ООО 'Альфа' & Омега <Беларусь></address>
Этот метод считается предпочтительным, так как исключает риск ошибки программиста при написании функций замены.
Если вы не хотите менять код обработки, а вам нужно быстро исправить данные в базе, выполните следующие шаги:
Важное примечание для пользователей из Беларуси: портал ЭСЧФ очень чувствителен к кодировке. Убедитесь, что ваш XML формируется в кодировке UTF-8. Если вы используете стандартную запись в файл через Текст.Записать(), помните, что 1С 7.7 пишет файлы в кодировке ANSI (Windows-1251). Для корректной работы с UTF-8 в 7.7 рекомендуется использовать объект ADODB.Stream.
Таким образом, мы выяснили, что стабильность выгрузки ЭСЧФ напрямую зависит от чистоты данных. Использование функции экранирования символов или переход на работу через DOMDocument позволит вам навсегда забыть об ошибках XML при выгрузке документов.