При интеграции 1С с внешними информационными системами (будь то государственные порталы, личные кабинеты контрагентов, системы маркировки «Честный Знак» или веб-сервисы) разработчики регулярно сталкиваются с необходимостью формирования файлов в формате XML. На первый взгляд, задача кажется тривиальной, однако при детальной реализации возникает множество нюансов: от корректной вставки служебных комментариев до обработки пустых значений и прохождения валидации по XSD-схемам.
В этой статье мы подробно разберем, как правильно решать технические проблемы, возникающие при ручной генерации XML-документов в 1С, проанализируем архитектурные подходы и рассмотрим примеры кода, которые помогут избежать распространенных ошибок.
Рассмотрим ситуацию, когда в готовом шаблоне XML-документа присутствуют элементы вида <!-- 1 -->. Попытка записать их как обычные элементы через метод ЗаписатьНачалоЭлемента(), например, вызвав Запись.ЗаписатьНачалоЭлемента("!-- 1 --"), является грубой ошибкой. Имена тегов в XML не могут начинаться с восклицательного знака или содержать дефисы в служебных позициях. Платформа 1С выдаст ошибку времени выполнения, либо на выходе получится некорректная разметка, которую не примет ни один парсер.
Для создания комментариев в структуре XML-документа на платформе 1С предусмотрено два стандартных и безопасных пути. Выясним особенности каждого из них.
Способ 1. Использование специализированного метода ЗаписатьКомментарий()
У объекта ЗаписьXML существует встроенный метод, предназначенный специально для вывода комментариев. Он автоматически обрамляет переданный текст в угловые скобки с восклицательным знаком и дефисами <!-- -->. Посмотрим на пример кода:
// Инициализируем объект записи XML
Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл("C:\temp\export.xml", "UTF-8");
Запись.ЗаписатьОбъявлениеXML();
Запись.ЗаписатьНачалоЭлемента("Root");
// Записываем комментарий средствами платформы
Запись.ЗаписатьКомментарий(" 1 ");
Запись.ЗаписатьКонецЭлемента(); // Root
Запись.Закрыть();
В результате выполнения этого кода в итоговом файле сформируется абсолютно корректная и валидная строка:
<!-- 1 -->
Способ 2. Использование метода ЗаписатьБезОбработки()
В некоторых случаях вам может потребоваться вставить сложную, жестко заданную статическую разметку или специфический блок комментариев, не полагаясь на автоматическое форматирование платформы. Для этого отлично подходит метод ЗаписатьБезОбработки(). Проанализируем следующий пример:
Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл("C:\temp\export.xml", "UTF-8");
Запись.ЗаписатьОбъявлениеXML();
Запись.ЗаписатьНачалоЭлемента("Root");
// Платформа запишет строку ровно в том виде, в котором мы ее передали
Запись.ЗаписатьБезОбработки("<!-- 1 -->");
Запись.ЗаписатьКонецЭлемента();
Запись.Закрыть();
Важное предупреждение: Метод ЗаписатьБезОбработки() обходит стандартные механизмы валидации платформы 1С. Если вы допустите синтаксическую ошибку в передаваемой строке (например, забудете закрыть скобку или кавычку), результирующий XML-документ станет нечитаемым для принимающей стороны. Используйте этот метод осмотрительно.
Еще один частый вопрос разработчиков: нужно ли обязательно выгружать теги, для которых в базе 1С нет данных? Можно ли их просто пропустить или обязательно передавать пустыми? Решение этой дилеммы полностью зависит от требований схемы XML (XSD-файла), по которой принимающая сторона проверяет ваш файл.
Разберем по шагам, как ведут себя элементы в зависимости от параметров схемы:
minOccurs (минимальное число вхождений):
Если в XSD-схеме для элемента указано свойство minOccurs="0", это означает, что элемент является необязательным. Если данных для него в 1С нет, мы можем полностью опустить запись этого тега. Приемник успешно обработает файл.
Если же minOccurs="1" (или этот атрибут вовсе не указан, что по умолчанию означает обязательность), то тег обязан присутствовать в XML-документе. Просто пропустить его нельзя — это вызовет ошибку валидации на стороне приемника.
nillable="true" (в 1С соответствует свойству XDTO ВозможноПустое):
Если элемент обязателен для присутствия, но пуст по значению (например, незаполненный реквизит «Дата рождения» или «Сумма»), простая запись вида <DateOfBirth></DateOfBirth> для строго типизированных полей вызовет ошибку парсинга. Для обхода этого ограничения в XSD-схемах используется признак "nillable".
Если схема допускает пустоту (nillable="true"), в XML-файл необходимо передать специальный признак отсутствия значения:
<DateOfBirth xsi:nil="true"/>
Чтобы избавить себя от гадания на тему «примет ли портал наш файл», мы можем организовать автоматическую проверку сформированного XML прямо в коде 1С перед отправкой. Для этого нам понадобится файл XSD-схемы. Разберем пример реализации такой проверки с помощью механизма фабрики XDTO:
ПутьКФайлуСхемы = "C:\schemas\FES_Format.xsd";
ПутьКВыгруженномуФайлу = "C:\temp\export.xml";
Попытка
// Создаем фабрику XDTO на основании схемы приемника
НоваяФабрика = СоздатьФабрикуXDTO(ПутьКФайлуСхемы);
// Инициализируем чтение XML-документа
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ПутьКВыгруженномуФайлу);
// Выполняем валидацию структуры и типов данных
НоваяФабрика.Проверить(Чтение);
Сообщить("Успешно! XML-файл полностью соответствует XSD-схеме.");
Чтение.Закрыть();
Исключение
// Сюда мы попадем, если в файле не хватает обязательных тегов или нарушен их формат
Сообщить("Ошибка валидации XML: " + ОписаниеОшибки(), СтатусСообщения.Важное);
Если Чтение <> Неопределено Тогда
Чтение.Закрыть();
КонецЕсли;
КонецПопытки;
В процессе разработки часто возникает соблазн написать выгрузку «по-быстрому» через последовательный вызов методов ЗаписатьНачалоЭлемента() и ЗаписатьКонецЭлемента(). Однако ручное формирование структуры таит в себе скрытые опасности, которые могут проявиться только в промышленной эксплуатации.
Проблема 1. Спецсимволы в текстовых полях
Если в наименовании контрагента, номенклатуры или в адресе содержатся символы, являющиеся служебными для разметки XML (например, &, <, >, ", '), прямая их запись в файл разрушит всю структуру. Документ перестанет открываться. При ручной записи необходимо обязательно экранировать данные с помощью функции платформы XMLСтрока():
// Опасный вариант (может сломать XML, если в наименовании есть символ "&")
Запись.ЗаписатьТекст(Выборка.НаименованиеКонтрагента);
// Безопасный вариант с автоматическим экранированием спецсимволов
Запись.ЗаписатьТекст(XMLСтрока(Выборка.НаименованиеКонтрагента));
Проблема 2. Строгий порядок следования элементов
Большинство официальных XSD-схем требуют, чтобы элементы внутри родительского тега шли в строго определенном порядке (в схеме это задается контейнером <xs:sequence>). Если вы при ручном кодинге случайно перепутаете строки и запишете, например, тег <ИНН> после тега <КПП>, хотя в схеме описан обратный порядок, принимающий шлюз отклонит ваш файл.
Использование объектной модели XDTO (XML Data Transfer Objects) полностью решает эту проблему. Вы наполняете свойства объекта 1С в любом удобном для вас порядке в коде, а платформа при сериализации в XML сама выстраивает элементы в строгом соответствии с требованиями импортированной схемы.
В современной практике 1С-разработчики чаще всего сталкиваются со сложными требованиями XML-форматов в двух сферах: передача сведений в Росфинмониторинг (ФЭС по 115-ФЗ) и интеграция с государственной информационной системой маркировки товаров (ГИС МТ «Честный Знак»). Разберем их специфику.
Формализованные электронные сообщения (ФЭС 115-ФЗ)
Форматы ФЭС содержат сотни обязательных реквизитов с жесткой иерархией. Пытаться собирать такой XML вручную через цепочки ЗаписатьНачалоЭлемента() крайне нерационально и трудоемко. При любом минимальном изменении законодательства вам придется переписывать сотни строк процедур выгрузки. Единственным верным решением здесь является импорт XSD-схемы Росфинмониторинга в конфигурацию в качестве XDTO-пакета и заполнение структуры через объекты XDTO.
Маркировка («Честный Знак»)
При передаче сведений о кодах маркировки (например, при вводе товаров в оборот или их списании в личном кабинете ГИС МТ) возникает специфическая проблема. Сами коды DataMatrix содержат в себе скрытые и непечатные спецсимволы, такие как разделитель групп GS1 (символ с кодом ASCII 29, известный как FNC1). Если записать такой код напрямую, XML-парсер на стороне Честного Знака выдаст синтаксическую ошибку.
Чтобы избежать искажения кодов маркировки и сбоев при импорте, стандарты обмена требуют оборачивать строки с кодами в специальные секции CDATA (Character Data), которые говорят парсеру, что внутри находится чистый текст, который не нужно пытаться интерпретировать как разметку.
Посмотрим, как реализовать запись тегов с секцией CDATA в 1С:
// Предположим, у нас есть код маркировки со спецсимволами
КодМаркировки = "01046000000000215gY&tYtr" + Символ(29) + "91EE06" + Символ(29) + "92yH";
Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл("C:\temp\marking.xml", "UTF-8");
Запись.ЗаписатьОбъявлениеXML();
Запись.ЗаписатьНачалоЭлемента("ki_code");
// Записываем значение в безопасную секцию CDATA
Запись.ЗаписатьСекциюCDATA(КодМаркировки);
Запись.ЗаписатьКонецЭлемента(); // ki_code
Запись.Закрыть();
В результирующем XML-файле мы получим абсолютно корректную структуру, готовую к успешной загрузке в личный кабинет системы маркировки:
<ki_code><![CDATA[01046000000000215gY&tYtr91EE0692yH]]></ki_code>
Подводя итог, отметим: если перед вами стоит задача быстро скорректировать существующую ручную выгрузку (особенно в условиях сжатых сроков), то точечное использование методов ЗаписатьКомментарий(), XMLСтрока() и секций CDATA позволит быстро и безболезненно решить проблему. Однако при проектировании новых масштабных интеграций всегда отдавайте предпочтение механизму XDTO, который гарантирует жесткое соблюдение стандартов и экономит время при последующей поддержке кода.