Как устроен XML-файл, который пишет и читает 1С
Содержание
Структура XML в 1С зависит от того, кто формирует файл. Если файл пишет платформа через ЗаписатьXML(), корневой тег — имя объекта метаданных (DocumentObject.РеализацияТоваровУслуг), внутри — стандартные реквизиты на английском (Ref, Date, Number) и реквизиты конфигурации на русском. Если файл строится по пакету XDTO или правилам конвертации, схему задаёт XSD или формат обмена, а не конфигурация.
На практике встречаются три схемы: сериализация XDTO «как есть», сообщения планов обмена и форматы конвертации (EnterpriseData, «Конвертация данных 2.x»). Первую выбирают для переноса между одинаковыми конфигурациями, вторую — для распределённых баз, третью — когда конфигурации разные. Ниже — как выглядит каждый файл, какие типы во что превращаются и как не утонуть в гигабайтной выгрузке.
Три схемы XML-файлов в 1С и когда какая нужна
| Схема | Кто формирует | Корневой элемент | Когда выбирают |
|---|---|---|---|
| Сериализация XDTO | ЗаписатьXML(), СериализаторXDTO | имя объекта: CatalogObject.Номенклатура | перенос между базами с одной конфигурацией |
| Сообщение обмена | ПланыОбмена.СоздатьЗаписьСообщения() | v8msg:Message с Header и Body | РИБ и обмены по плану обмена |
| EnterpriseData | БСП, обработчики конвертации | Message в пространстве .../EnterpriseData/... | обмен разных конфигураций: БП, УТ, ERP |
| Конвертация данных 2.x | правила из КД 2 | ФайлОбмена с атрибутом ВерсияФормата | старые обмены через универсальный формат |
Схемы не смешиваются. Файл, выгруженный обработкой «Выгрузка и загрузка данных XML», не загрузится через правила EnterpriseData, и наоборот. Перед разбором чужого файла откройте его в любом текстовом редакторе и посмотрите на корневой тег и атрибут xmlns — это сразу скажет, с какой схемой вы имеете дело.
Выгрузка конфигурации в файлы (1cv8 DESIGNER ... /DumpConfigToFiles) тоже даёт XML, но это описание метаданных, а не данных. Это отдельная структура, к обмену она не относится.
Как 1С сериализует объект: ЗаписатьXML и ПрочитатьXML
Сериализация — превращение объекта конфигурации в XML и обратно. Платформа делает это сама, по метаданным: свою схему писать не нужно.
Ключевые объекты встроенного языка:
- 📝
ЗаписьXML— потоковая запись файла или строки; - 📖
ЧтениеXML— потоковое чтение, узел за узлом; - 🔄
ЗаписатьXML()иПрочитатьXML()— глобальные методы, которые сериализуют объект целиком; - 🧩
СериализаторXDTO— то же, но с промежуточнымОбъектXDTO, если его нужно доработать перед записью.
Минимальная выгрузка одного документа выполняется на сервере:
&НаСервереБезКонтекста
Процедура ВыгрузитьДокумент(Ссылка, ИмяФайла)
Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл(ИмяФайла, "UTF-8");
Запись.ЗаписатьОбъявлениеXML();
ЗаписатьXML(Запись, Ссылка.ПолучитьОбъект());
Запись.Закрыть();
КонецПроцедуры
Сериализуется объект, а не ссылка. Если передать в ЗаписатьXML() саму ссылку, в файл попадёт только GUID — без реквизитов и табличных частей.
Загрузка — обратная операция. ПрочитатьXML() по имени корневого тега понимает, какой объект создать, находит его по GUID из Ref или создаёт новый с этим идентификатором. Записывать загруженный объект лучше в режиме обмена:
Объект = ПрочитатьXML(Чтение);
Объект.ОбменДанными.Загрузка = Истина;
Объект.Записать();
Флаг ОбменДанными.Загрузка отключает проверки и обработчики ПередЗаписью и ОбработкаПроверкиЗаполнения в типовом коде. Без него загрузка падает на первом документе, у которого пока нет контрагента или склада.
Документ в режиме загрузки записывается без формирования движений. Признак Posted переносится, но регистры остаются пустыми. Движения либо выгружают отдельно как наборы записей, либо документы перепроводят после загрузки.
Пакеты XDTO: когда структуру файла задаёт схема
Сериализация «как есть» подходит, пока обе стороны — 1С с одинаковыми метаданными. Как только файл нужен внешней системе (банку, маркетплейсу, сервису поставщика), структуру диктует чужая XSD-схема. Для этого в 1С есть XDTO.
Как это устроено:
- 📦 XSD-схему импортируют в конфигурацию: в дереве метаданных
Общие → XDTO-пакеты, команда импорта схемы. Пакет получает пространство имён изtargetNamespaceсхемы. - 🏭 Типы пакета доступны через глобальную
ФабрикаXDTO. Если менять конфигурацию нельзя, фабрику строят «на лету» из файла схемы функциейСоздатьФабрикуXDTO(). - 🧱 По типу создают
ОбъектXDTO, заполняют свойства и пишут черезФабрика.ЗаписатьXML().
Фабрика = СоздатьФабрикуXDTO("C:\schemas\order.xsd");
ТипЗаказа = Фабрика.Тип("http://example.org/order", "Order");
Заказ = Фабрика.Создать(ТипЗаказа);
Заказ.Number = "15";
Заказ.Date = ТекущаяДатаСеанса();
Заказ.Проверить(); // исключение, если объект не соответствует схеме
Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл("C:\exchange\order_15.xml", "UTF-8");
Запись.ЗаписатьОбъявлениеXML();
Фабрика.ЗаписатьXML(Запись, Заказ);
Запись.Закрыть();
Чтение идёт тем же путём: Фабрика.ПрочитатьXML(Чтение, ТипЗаказа) возвращает ОбъектXDTO, к полям которого обращаются через точку. Имена свойств совпадают с именами элементов схемы, поэтому они обычно латиницей.
Разница с сериализацией в одной фразе: в XDTO-пакете вы сами решаете, где лежат данные из 1С. Сопоставление «поле схемы → реквизит» пишется кодом, и это главный объём работы в любой интеграции.
Разбор XML-файла документа по тегам
Так выглядит выгрузка поступления товаров через ЗаписатьXML() (сокращённо, GUID обрезаны для читаемости):
<?xml version="1.0" encoding="UTF-8"?>
<DocumentObject.ПоступлениеТоваровУслуг
xmlns="http://v8.1c.ru/8.1/data/enterprise/current-config"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Ref>4f1b2c3d-...-0050568a1b2c</Ref>
<DeletionMark>false</DeletionMark>
<Date>2026-03-15T10:24:00</Date>
<Number>0000-000042</Number>
<Posted>true</Posted>
<Организация>9a8b7c6d-...-0050568a1b2c</Организация>
<Контрагент>1e2f3a4b-...-0050568a1b2c</Контрагент>
<ВидОперации>Товары</ВидОперации>
<СуммаДокумента>12500</СуммаДокумента>
<Товары>
<Row>
<Номенклатура>5c6d7e8f-...-0050568a1b2c</Номенклатура>
<Количество>10</Количество>
<Цена>1250</Цена>
<Сумма>12500</Сумма>
</Row>
</Товары>
</DocumentObject.ПоступлениеТоваровУслуг>
Что здесь важно:
- 🏷️ Корневой тег = вид объекта + имя в метаданных. Для справочника —
CatalogObject.Имя, для регистра сведений —InformationRegisterRecordSet.Имя. - 🌐 Пространство имён
.../current-configозначает «текущая конфигурация». Отсюда и требование: в базе-приёмнике должны быть объекты с теми же именами. - 🔑
Ref— GUID объекта. По нему загрузка находит существующий документ и перезаписывает его, а не создаёт дубль. - 🔗 Ссылочные реквизиты (
Организация,Контрагент) хранят только GUID. Самих контрагентов в файле нет — их нужно выгрузить отдельно. - 📋 Табличная часть — элемент с её именем, каждая строка —
Row. - 📛 Значение перечисления (
ВидОперации) пишется по имени значения, а не по синониму.
Последний пункт часто ломает загрузку. Если в приёмнике значение перечисления переименовали, ПрочитатьXML() выдаст исключение, хотя синоним у значения тот же.
Таблица соответствия типов данных 1С и XML
| Тип в 1С | Как выглядит в XML | Пример значения |
|---|---|---|
| Строка | xs:string | ООО «Ромашка» |
| Число | xs:decimal, разделитель — точка | 1250.5 |
| Дата | xs:dateTime | 2026-03-15T10:24:00 |
| Пустая дата | минимальная дата | 0001-01-01T00:00:00 |
| Булево | xs:boolean | true / false |
| Ссылка на справочник или документ | GUID строкой | 5c6d7e8f-... |
| Пустая ссылка | нулевой GUID | 00000000-0000-0000-0000-000000000000 |
| Перечисление | имя значения | Товары |
| УникальныйИдентификатор | строка UUID | 4f1b2c3d-... |
| ДвоичныеДанные, ХранилищеЗначения | xs:base64Binary | длинная строка base64 |
| Составной тип | значение + атрибут xsi:type | xsi:type="CatalogRef.Контрагенты" |
| Неопределено | пустой элемент с xsi:nil="true" | <Субконто1 xsi:nil="true"/> |
Составной тип — самое неочевидное место. Если реквизит может хранить и контрагента, и физлицо, по одному GUID не понять, куда ссылаться. Поэтому платформа дописывает тип:
<Субконто1 xsi:type="CatalogRef.Контрагенты">1e2f3a4b-...</Субконто1>
Для примитивов в составном типе пишется XSD-тип: xsi:type="xs:string" или xsi:type="xs:decimal".
Даты в сериализации идут без часового пояса. Если файл уходит во внешнюю систему, договоритесь о поясе заранее, иначе документ «съедет» на три часа.
ХранилищеЗначения раздувает файл сильнее всего: картинки номенклатуры и присоединённые файлы превращаются в base64, и объём растёт примерно на треть от исходного размера. Для переноса справочников без вложений такие реквизиты лучше очистить на стороне выгрузки.
Иерархия, табличные части и вложенные структуры в XML
Иерархия справочника. Вложенности тегов нет: группы и элементы лежат в файле на одном уровне. Связь задаёт реквизит Parent с GUID группы, а признак группы — IsFolder:
<CatalogObject.Номенклатура>
<Ref>aa11...</Ref>
<IsFolder>false</IsFolder>
<Parent>bb22...</Parent>
<Code>00-00000123</Code>
<Description>Бумага А4</Description>
</CatalogObject.Номенклатура>
Порядок загрузки групп и элементов при этом не критичен. Ссылка по GUID записывается, даже если группа ещё не загружена: до её появления в базе будет «битая» ссылка, после — нормальная.
Наборы записей регистров. Регистр выгружается не записью, а набором: внутри Filter (отбор по измерению или регистратору) и Records со строками Record. При загрузке набор с тем же отбором заменяет существующие записи целиком — учитывайте это, если выгружаете регистр частями.
Универсальные коллекции. Массив, Структура, Соответствие и ТаблицаЗначений тоже сериализуются, но в другом пространстве имён — http://v8.1c.ru/8.1/data/core. Значения внутри помечаются xsi:type. Это удобно, чтобы передать параметры между базами или сохранить настройки в файл.
Свой формат вложенности. Когда нужна именно вложенная структура (заказ → строки → серии), её пишут вручную через ЗаписьXML:
Запись.ЗаписатьНачалоЭлемента("Order");
Запись.ЗаписатьАтрибут("number", Документ.Номер);
Для Каждого Строка Из Документ.Товары Цикл
Запись.ЗаписатьНачалоЭлемента("Item");
Запись.ЗаписатьАтрибут("sku", Строка.Номенклатура.Артикул);
Запись.ЗаписатьАтрибут("qty", XMLСтрока(Строка.Количество));
Запись.ЗаписатьКонецЭлемента(); // Item
КонецЦикла;
Запись.ЗаписатьКонецЭлемента(); // Order
Функция XMLСтрока() переводит число, дату и булево в XML-представление: точка вместо запятой, без пробелов-разделителей разрядов, дата в формате ISO. Обычное Строка(Число) даст 1 250,5 — внешняя система такое не разберёт.
Проверка и оптимизация XML при обмене
Объявляйте пространства имён один раз. Если писать много объектов подряд, каждый тянет за собой xmlns:xs и xmlns:xsi. На десятках тысяч объектов это мегабайты повторов. Решение — общий корневой элемент с объявлениями:
Запись.ЗаписатьНачалоЭлемента("Data");
Запись.ЗаписатьСоответствиеПространстваИмен("xs", "http://www.w3.org/2001/XMLSchema");
Запись.ЗаписатьСоответствиеПространстваИмен("xsi", "http://www.w3.org/2001/XMLSchema-instance");
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
ЗаписатьXML(Запись, Выборка.ПолучитьОбъект());
КонецЦикла;
Запись.ЗаписатьКонецЭлемента();
Читайте потоком, а не DOM. ДокументDOM грузит весь файл в память. Для файла на 2 ГБ серверу понадобится в разы больше оперативной памяти. ЧтениеXML идёт по узлам и держит в памяти один объект:
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ИмяФайла);
Чтение.ПерейтиКСодержимому(); // корневой Data
Чтение.Прочитать(); // первый объект внутри
Пока ВозможностьЧтенияXML(Чтение) Цикл
Объект = ПрочитатьXML(Чтение);
Объект.ОбменДанными.Загрузка = Истина;
Объект.Записать();
КонецЦикла;
Чтение.Закрыть();
ВозможностьЧтенияXML() возвращает Ложь, когда текущий узел — не объект, который платформа умеет прочитать (например, закрывающий тег Data). Так цикл останавливается сам.
Проверяйте по схеме до отправки. Для XDTO-объектов есть Проверить(): он вызывает исключение с описанием нарушенного ограничения (пропущено обязательное поле, строка длиннее maxLength). Вызывайте его в попытке и пишите текст ошибки в журнал регистрации — так видно, какой документ и какое поле не прошли.
Кодировка — только UTF-8. Указывайте её явно в ОткрытьФайл() и в объявлении. Файл в Windows-1251 без объявления кодировки даст кракозябры в наименованиях у получателя.
Частые вопросы
Можно ли перенести данные XML-выгрузкой между БП и УТ?
Чем выгрузить справочник в XML без программирования?
Почему стандартные теги на английском, а реквизиты на русском?
Ref, Code, Description, Parent) общие для платформы и пишутся по внутренним именам. Реквизиты конфигурации идут по именам из метаданных, как их задал разработчик.Изменится ли GUID объекта после загрузки?
ПрочитатьXML() создаёт объект с идентификатором из Ref, поэтому повторная загрузка того же файла обновит объекты, а не создаст дубли.