При выгрузке данных из 1С в формат XML начинающие разработчики часто сталкиваются с трудностями при попытке записать ссылочные типы, такие как СправочникСсылка.Организации. Основные проблемы возникают из-за непонимания разницы между атрибутами и элементами XML, а также из-за нюансов преобразования типов данных. В этой статье мы подробно разберем, как избежать ошибки «Несоответствие типов», почему файл может оказаться пустым и какой способ записи является наиболее эффективным.
Рассмотрим ситуацию, когда необходимо получить в XML-файле строку вида: <v8:Организация xsi:type="v8:CatalogRef.Организации">b5eee258...</v8:Организация>. Попытка использовать для этого метод ЗаписатьАтрибут является архитектурной ошибкой. Проанализируем почему.
В терминологии XML атрибут — это дополнительная информация, которая пишется внутри открывающего тега, например: <Организация Тип="Справочник">. То, что требуется получить в задаче — это полноценный элемент (или узел), который имеет имя, префикс пространства имен, атрибуты и текстовое содержимое (GUID).
Для создания такой структуры вручную нам потребуется последовательность команд, а не одна функция. Кроме того, важно помнить, что метод ЗаписатьАтрибут вторым параметром всегда ожидает строку. Если передать туда объект типа СправочникСсылка, система закономерно выдаст ошибку «Несоответствие типов».
Если мы решим пойти по пути ручного формирования XML, нам необходимо выполнить преобразование ссылки в строковый идентификатор и правильно открыть/закрыть теги. Рассмотрим этот процесс по шагам:
Посмотрим на пример кода, реализующий этот подход:
// 1. Находим организацию (лучше использовать ИНН)
ОрганизацияСсылка = Справочники.Организации.НайтиПоНаименованию("СНТ ""Металлург-3""");
Если Не ОрганизацияСсылка.Пустая() Тогда
// 2. Получаем строковое представление GUID
Идентификатор = Строка(ОрганизацияСсылка.УникальныйИдентификатор());
// 3. Записываем элемент вручную
ЗаписьXML.ЗаписатьНачалоЭлемента("v8:Организация");
// Если нужно добавить тип как атрибут
ЗаписьXML.ЗаписатьАтрибут("xsi:type", "v8:CatalogRef.Организации");
// Записываем сам GUID
ЗаписьXML.ЗаписатьТекст(Идентификатор);
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЕсли;
Важный момент: Строка(ОрганизацияСсылка) вернет наименование организации (например, "Металлург-3"), а не её GUID. Чтобы получить именно идентификатор (вроде b5eee258-3e95...), обязательно нужно использовать метод УникальныйИдентификатор().
Проанализируем более современный и надежный метод. В платформе 1С существует встроенный механизм — Сериализатор XDTO. Он специально создан для того, чтобы автоматически преобразовывать объекты 1С в формат XML, соответствующий стандартам платформы.
Этот метод самостоятельно добавит атрибут xsi:type, правильно обработает пространства имен и запишет идентификатор. Это избавляет разработчика от необходимости вручную прописывать каждый тег.
Рассмотрим, как упрощается код при использовании этого подхода:
// Получаем ссылку на организацию
СсылкаНаОбъект = Справочники.Организации.НайтиПоНаименованию("Металлург-3");
// Используем Сериализатор для автоматической записи
// Параметры: ОбъектЗаписи, Ссылка, ИмяУзла, ПространствоИмен
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, СсылкаНаОбъект, "Организация", "http://v8.1c.ru/8.1/data/enterprise/current-config");
При таком подходе вероятность совершить ошибку в именах атрибутов или типах данных сводится к минимуму. Платформа сама знает, как должен выглядеть тип v8:CatalogRef.Организации в структуре XML.
Выясним причину ситуации, когда код вроде бы выполняется без ошибок, но результирующий файл имеет нулевой размер. Это одна из самых частых проблем при работе с объектом ЗаписьXML.
Дело в том, что запись в файл в 1С происходит через буфер. Данные сначала накапливаются в оперативной памяти и сбрасываются на жесткий диск только при заполнении буфера или при явном закрытии объекта. Если вы забыли вызвать метод Закрыть(), то при завершении работы процедуры объект уничтожается, а данные из буфера так и не записываются в файл.
Всегда используйте следующую структуру при работе с файлами:
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл("C:\temp\export.xml", "UTF-8");
// ... здесь логика записи данных ...
// Обязательный метод для сохранения данных на диск!
ЗаписьXML.Закрыть();
В примере автора сообщения фигурируют префиксы v8: и xsi:. Чтобы XML-файл был валидным и эти префиксы распознавались другими системами, их нужно объявить. Обычно это делается в корневом элементе файла. Если вы используете СериализаторXDTO, он может сделать это автоматически, но при ручной записи стоит использовать метод ЗаписатьСоответствиеПространствИмен.
Проанализируем пример объявления пространств:
ЗаписьXML.ЗаписатьНачалоЭлемента("Данные");
ЗаписьXML.ЗаписатьСоответствиеПространствИмен("v8", "http://v8.1c.ru/8.1/data/core");
ЗаписьXML.ЗаписатьСоответствиеПространствИмен("xsi", "http://www.w3.org/2001/XMLSchema-instance");
// Теперь можно записывать вложенные элементы с этими префиксами
Для корректной выгрузки ссылок в XML мы рекомендуем придерживаться следующих правил:
УникальныйИдентификатор().Ссылка.Пустая()), чтобы не выгружать "нулевые" GUID.ЗаписьXML.Закрыть() — критически важный этап для физического сохранения файла.Следуя этим рекомендациям, вы сможете создавать корректные и структурированные XML-файлы, которые будут легко читаться как в 1С, так и во внешних информационных системах.