При работе с внешними системами и тестировании http сервисов часто возникает задача выгрузки данных из 1С в формате XML, строго соответствующем предоставленной схеме XSD (также часто применяется выгрузка в формате JSON) — для этого подойдёт универсальная обработка выгрузки в XML и JSON с гибкой настройкой структуры. Эта задача может вызвать вопросы, особенно если нет примера готового XML-файла. В этом поможет анализ структуры метаданных. В этом руководстве мы подробно рассмотрим, как подойти к этой проблеме, используя инструментарий 1С, такой как ФабрикаXDTO и ОбъектыXDTO.
Начнем с того, что схема XSD (XML Schema Definition) описывает структуру XML-документа: какие элементы и атрибуты могут быть, их типы данных, порядок следования, обязательность и количество повторений. Наша задача — "перевести" это описание в объекты 1С, заполнить их данными и затем сериализовать в XML-файл.
Прежде чем мы начнем работать с XSD-схемой программно, нам необходимо корректно ее обработать и, при необходимости, импортировать в конфигурацию 1С. Иногда XSD-файлы содержат ссылки на другие схемы (секция xsd:import), что может вызвать проблемы при импорте или создании ФабрикиXDTO напрямую из файла. В таком случае, мы рекомендуем выполнить следующие шаги:
.xsd.<xsd:import>, если они есть и вызывают ошибки при работе с файлом. Важно: Делайте это только в том случае, если вы уверены, что импортируемые схемы не являются критически важными для основной структуры, или если у вас есть все необходимые файлы XSD в одном каталоге и вы планируете создать набор схем.Этот шаг является необязательным для программного создания ФабрикиXDTO, но он удобен для визуализации структуры схемы и работы с ней в дальнейшем, если вы планируете использовать эти типы многократно.
Первый программный шаг — это создание объекта ФабрикаXDTO, который будет "знать" о всех типах, определенных в нашей XSD-схеме. ФабрикаXDTO — это центральный объект для работы с XDTO в 1С. Мы можем создать ее либо на основе уже импортированной в конфигурацию схемы, либо непосредственно из файла XSD.
Рассмотрим пример создания ФабрикиXDTO из файла XSD. Этот подход полезен, когда схему не нужно жестко встраивать в конфигурацию, или она часто меняется.
// Пусть Сайт - это путь к файлу XSD.
// Например: Сайт = "C:\МоиСхемы\МояСхема.xsd";
// Создадим фабрику XDTO на основе схемы XML, содержащейся в файле XSD.
// 1. Создадим объект чтения XML по умолчанию.
НовоеЧтениеXML = Новый ЧтениеXML;
// 2. Откроем файл XSD.
// Важно: здесь мы открываем XSD как обычный XML-файл для чтения его содержимого.
Попытка
НовоеЧтениеXML.ОткрытьФайл(Сайт);
Исключение
Сообщить("Не удалось открыть файл XSD: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// 3. Создадим построитель документа DOM по умолчанию.
НовыйПостроительDOM = Новый ПостроительDOM;
// 4. Прочитаем файл XSD в документ DOM.
// Это позволяет получить древовидное представление структуры XSD в памяти.
Попытка
НовыйДокументDOM = НовыйПостроительDOM.Прочитать(НовоеЧтениеXML);
Исключение
Сообщить("Ошибка при чтении XSD в DOM: " + ОписаниеОшибки());
НовоеЧтениеXML.Закрыть();
Возврат;
КонецПопытки;
// Обязательно закроем объект чтения XML после использования.
НовоеЧтениеXML.Закрыть();
// 5. Создадим построитель схемы XML по умолчанию.
НовыйПостроительСхемXML = Новый ПостроительСхемXML;
// 6. Получим схему XML из документа DOM.
// Этот шаг интерпретирует DOM-представление XSD в объект 1С: СхемаXML.
Попытка
НоваяСхемаXML = НовыйПостроительСхемXML.СоздатьСхемуXML(НовыйДокументDOM);
Исключение
Сообщить("Ошибка при создании СхемыXML из DOM: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// 7. Создадим набор схем XML по умолчанию.
// Набор схем позволяет объединить несколько XSD-схем, если они взаимосвязаны.
НовыйНаборСхемXML = Новый НаборСхемXML;
// 8. Добавим нашу схему XML в набор схем XML.
НовыйНаборСхемXML.Добавить(НоваяСхемаXML);
// 9. Создадим ФабрикуXDTO на основе набора схем XML.
// Теперь ФабрикаXDTO готова к работе и знает все типы, определенные в XSD.
НоваяФабрикаXDTO = Новый ФабрикаXDTO(НовыйНаборСхемXML);
// Для отладки и понимания структуры мы можем пройтись по пакетам и корневым свойствам:
Для Каждого Пакет Из НоваяФабрикаXDTO.Пакеты Цикл
Сообщить("Пакет: " + Пакет.Имя);
Для Каждого ТипXDTOСхемы Из Пакет.ВсеТипы Цикл
// Сообщить(" Тип: " + ТипXDTOСхемы.Имя);
КонецЦикла;
Для Каждого КорневоеСвойство Из Пакет.КорневыеСвойства Цикл
Сообщить(" Корневое свойство (элемент): " + КорневоеСвойство.Имя + " (Тип: " + КорневоеСвойство.Тип.Имя + ")");
КонецЦикла;
КонецЦикла;
Этот код позволяет динамически загрузить XSD-схему и создать работоспособную ФабрикуXDTO. Объект НоваяФабрикаXDTO теперь содержит всю информацию о типах данных, элементах и атрибутах, описанных в XSD, и готов к использованию для создания объектов XDTO.
Одна из самых сложных частей задачи — понять, как должен выглядеть итоговый XML-файл, если у вас есть только XSD-схема, но нет примера файла XML. Схема — это лишь описание возможных структур, а не конкретный пример. Тем не менее, мы можем "прочитать" ее, чтобы определить ожидаемый формат.
Каждый XML-документ имеет единственный корневой элемент. В XSD-схеме корневой элемент обычно определяется с помощью элемента <xs:element> на верхнем уровне, который не является частью сложного типа (complexType) другого элемента. Он часто имеет атрибут name, который соответствует имени корневого тега в XML-файле.
Например, в схеме Yandex Market Language (YML), корневым элементом является yml_catalog — для формирования такого файла есть готовая обработка выгрузки товаров на Яндекс Маркет в формате YML. Вы можете найти его в XSD-файле как:
<xs:element name="yml_catalog" type="yml_catalogType"/>
В этом случае yml_catalog — это имя корневого элемента, а yml_catalogType — сложный тип, который описывает его содержимое.
После определения корневого элемента необходимо изучить его complexType (сложный тип), который описывает содержимое этого элемента. Внутри complexType вы найдете:
<xs:sequence>: Элементы должны следовать в указанном порядке.<xs:choice>: Может быть выбран только один из перечисленных элементов.<xs:all>: Все перечисленные элементы должны присутствовать, но в любом порядке (редко используется).Внутри этих конструкций вы увидите дочерние элементы (<xs:element>) и их атрибуты (<xs:attribute>). Обращайте внимание на следующие атрибуты:
name: Имя элемента или атрибута.type: Тип данных элемента или атрибута (например, xs:string, xs:int, myCustomType).minOccurs: Минимальное количество вхождений (по умолчанию 1). Если 0, элемент необязательный.maxOccurs: Максимальное количество вхождений (по умолчанию 1). Если "unbounded", элемент может встречаться много раз (что означает список в 1С).use (для атрибутов): "required" (обязательный) или "optional" (необязательный).Например, если вы видите:
<xs:complexType name="yml_catalogType">
<xs:sequence>
<xs:element name="shop" type="shopType" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="date" type="xs:dateTime" use="required"/>
</xs:complexType>
Это означает, что корневой элемент yml_catalog должен содержать один или несколько элементов shop (потому что maxOccurs="unbounded") и обязательный атрибут date типа дата/время. Далее вам нужно будет изучить shopType.
anyTypeЕсли в схеме вы видите, что тип элемента определен как xs:anyType, это означает, что в этот элемент могут быть вложены вообще любые допустимые XML-элементы. Это существенно повышает вариативность и неопределенность. В 1С это может потребовать:
anyType, вы можете сформировать их как отдельные ОбъектыXDTO и присвоить их.anyType сложна или динамична, вы можете использовать метод ДобавитьПроизвольныйЭлемент для ОбъектаXDTO, чтобы вставить туда готовый XML-фрагмент (предварительно сформированный строкой или другим способом).Для более наглядного анализа XSD-схемы без примера XML-файла существуют сторонние инструменты и онлайн-сервисы, которые могут графически отображать структуру XSD (например, "XML Schema Viewer"). Они помогают визуализировать иерархию элементов, их типы и обязательность, делая схему гораздо более понятной.
Критически важно: Если есть возможность, всегда просите пример файла XML у разработчиков сервиса или того, кто предоставил схему. Это лучший способ точно определить, какая структура данных ожидается.
Теперь, когда у нас есть ФабрикаXDTO и мы понимаем структуру схемы, мы можем приступить к созданию и заполнению объектов, которые затем будут преобразованы в XML. В 1С для этого используются объекты типа ОбъектXDTO.
Чтобы создать ОбъектXDTO, нам нужно получить соответствующий тип из нашей ФабрикиXDTO. Типы организованы по пакетам (соответствующим целевым пространствам имен в XSD).
Если вы знаете имя пакета и имя типа (элемента), вы можете получить его так:
// Предположим, корневой элемент нашей схемы называется "yml_catalog"
// и находится в пакете с именем "http://market.yandex.ru" (или другим, указанным в схеме).
ИмяПакета = "http://market.yandex.ru"; // Или другое имя пакета из XSD
ИмяКорневогоТипа = "yml_catalogType"; // Или другое имя типа корневого элемента
// Получаем тип из ФабрикиXDTO
ТипКорневогоОбъектаXDTO = НоваяФабрикаXDTO.Пакеты[ИмяПакета].ПолучитьТип(ИмяКорневогоТипа);
Если ТипКорневогоОбъектаXDTO = Неопределено Тогда
Сообщить("Не удалось найти тип '" + ИмяКорневогоТипа + "' в пакете '" + ИмяПакета + "'. Проверьте XSD-схему и имена.");
Возврат;
КонецЕсли;
Если вы не уверены в имени пакета или типа, вы можете использовать циклы, как показано в примере создания ФабрикиXDTO, чтобы вывести все доступные пакеты и типы и найти нужный.
После получения нужного типа мы можем создать экземпляр ОбъектаXDTO с помощью метода Создать ФабрикиXDTO:
// Создаем корневой ОбъектXDTO
КорневойОбъектXDTO = НоваяФабрикаXDTO.Создать(ТипКорневогоОбъектаXDTO);
Заполнение ОбъектаXDTO происходит путем обращения к его свойствам, имена которых соответствуют именам дочерних элементов и атрибутов, определенных в XSD-схеме.
ОбъектXDTO для этого дочернего элемента, заполните его, а затем присвойте родительскому объекту.maxOccurs="unbounded"): Соответствующее свойство ОбъектаXDTO будет коллекцией (подобно массиву или списку значений в 1С). Вам нужно будет создавать новые ОбъектыXDTO для каждого элемента в списке и добавлять их в эту коллекцию.Рассмотрим гипотетический пример, основанный на структуре YML, где yml_catalog содержит shop, а shop содержит name и список offers: для автоматического создания таких файлов есть обработка формирования XML и YML по требованиям внешних площадок.
// --- 1. Заполняем корневой объект yml_catalog ---
// Установим атрибут 'date' для корневого элемента.
// В XSD это <xs:attribute name="date" type="xs:dateTime" use="required"/>
КорневойОбъектXDTO.Дата = ТекущаяДата(); // Атрибуты в 1С часто доступны как свойства с тем же именем
// --- 2. Создаем и заполняем элемент 'shop' ---
// Предположим, что тип для 'shop' называется "shopType" в том же пакете
ТипShopXDTO = НоваяФабрикаXDTO.Пакеты[ИмяПакета].ПолучитьТип("shopType");
Если ТипShopXDTO = Неопределено Тогда
Сообщить("Не удалось найти тип 'shopType'.");
Возврат;
КонецЕсли;
ОбъектShopXDTO = НоваяФабрикаXDTO.Создать(ТипShopXDTO);
// Заполняем простые свойства элемента 'shop'
ОбъектShopXDTO.Название = "Мой интернет-магазин"; // Соответствует <xs:element name="name" type="xs:string"/>
ОбъектShopXDTO.Компания = "ООО 'Пример'";
ОбъектShopXDTO.URL = "https://www.example.com";
// Добавляем заполненный ОбъектShopXDTO в коллекцию 'shop' корневого объекта.
// В нашем XSD-примере shop имел maxOccurs="unbounded", поэтому КорневойОбъектXDTO.Shop
// будет коллекцией.
// Важно: Имя свойства в 1С (например, КорневойОбъектXDTO.Shop) будет соответствовать
// имени элемента из схемы (xs:element name="shop").
КорневойОбъектXDTO.shop.Добавить(ОбъектShopXDTO);
// --- 3. Создаем и заполняем список 'offers' внутри 'shop' ---
// Предположим, что тип для 'offer' называется "offerType"
ТипOfferXDTO = НоваяФабрикаXDTO.Пакеты[ИмяПакета].ПолучитьТип("offerType");
Если ТипOfferXDTO = Неопределено Тогда
Сообщить("Не удалось найти тип 'offerType'.");
Возврат;
КонецЕсли;
// Добавляем первый товар (offer)
ОбъектOfferXDTO1 = НоваяФабрикаXDTO.Создать(ТипOfferXDTO);
ОбъектOfferXDTO1.Id = "12345"; // Атрибут id элемента offer
ОбъектOfferXDTO1.Доступен = Истина; // Атрибут available элемента offer
ОбъектOfferXDTO1.URL = "https://www.example.com/product/1";
ОбъектOfferXDTO1.Цена = 1000;
ОбъектOfferXDTO1.ВалютаId = "RUB";
ОбъектOfferXDTO1.Название = "Пример товара 1";
ОбъектOfferXDTO1.Описание = "Подробное описание первого товара.";
ОбъектShopXDTO.offers.Добавить(ОбъектOfferXDTO1); // 'offers' - это коллекция внутри 'shop'
// Добавляем второй товар (offer)
ОбъектOfferXDTO2 = НоваяФабрикаXDTO.Создать(ТипOfferXDTO);
ОбъектOfferXDTO2.Id = "67890";
ОбъектOfferXDTO2.Доступен = Ложь;
ОбъектOfferXDTO2.URL = "https://www.example.com/product/2";
ОбъектOfferXDTO2.Цена = 2500;
ОбъектOfferXDTO2.ВалютаId = "RUB";
ОбъектOfferXDTO2.Название = "Пример товара 2";
ОбъектOfferXDTO2.Описание = "Подробное описание второго товара.";
ОбъектShopXDTO.offers.Добавить(ОбъектOfferXDTO2);
Важно: При заполнении свойств ОбъектаXDTO имена свойств должны строго соответствовать именам элементов или атрибутов, определенным в XSD-схеме (с учетом регистра!). Если в схеме элемент называется "Price", то в 1С это будет ОбъектXDTO.Price, а не ОбъектXDTO.Цена.
После того как корневой ОбъектXDTO (и все его вложенные объекты) полностью заполнен данными из 1С, его можно записать в XML-файл. Для этого мы используем стандартные объекты 1С: ЗаписьXML и метод ЗаписатьXDTO.
// Путь к файлу, куда будет записан XML
ПутьКФайлуXML = "C:\МоиВыгрузки\output.xml";
// Создаем объект ЗаписьXML
ЗаписьXML = Новый ЗаписьXML;
Попытка
// Открываем файл для записи. Указываем кодировку UTF-8 (чаще всего используется).
// Стандартные отступы делают XML более читаемым.
ЗаписьXML.ОткрытьФайл(ПутьКФайлуXML, "UTF-8", СтандартныеОтступыXML.Истина);
// Записываем корневой ОбъектXDTO в файл.
// ФабрикаXDTO автоматически определяет правила сериализации на основе XSD.
НоваяФабрикаXDTO.ЗаписатьXDTO(ЗаписьXML, КорневойОбъектXDTO);
// Закрываем файл. Это ОБЯЗАТЕЛЬНО для сохранения данных.
ЗаписьXML.Закрыть();
Сообщить("XML-файл успешно выгружен по пути: " + ПутьКФайлуXML);
Исключение
Сообщить("Ошибка при записи XML-файла: " + ОписаниеОшибки());
Если ЗаписьXML.Открыт() Тогда
ЗаписьXML.Закрыть();
КонецЕсли;
КонецПопытки;
После выполнения этого кода на указанном пути будет создан XML-файл с данными, сформированными согласно XSD-схеме и заполненными из наших ОбъектовXDTO.
Если ваша XSD-схема использует пространства имен (targetNamespace), убедитесь, что они правильно обрабатываются. При импорте схемы в 1С или при создании ФабрикиXDTO, 1С обычно автоматически учитывает пространства имен. При обращении к типам через ФабрикаXDTO.Пакеты[ИмяПакета], ИмяПакета часто соответствует целевому пространству имен (targetNamespace), указанному в XSD.
В 1С нет встроенных средств для валидации сгенерированного XML-файла по XSD-схеме после его создания. Для полной уверенности в корректности сгенерированного файла и его соответствии XSD-схеме рекомендуется использовать внешние инструменты валидации XML. Существуют как онлайн-валидаторы, так и десктопные приложения (например, XMLSpy, Oxygen XML Editor, или бесплатные утилиты типа xmllint), которые могут точно указать на любые несоответствия схеме. При необходимости выполнять такую проверку непосредственно в базе 1С можно использовать обработку для валидации XML-файлов на соответствие XSD-схеме.
При возникновении ошибок при записи XML или при его некорректном формировании, используйте отладчик 1С. Вы можете поставить точку останова перед вызовом НоваяФабрикаXDTO.ЗаписатьXDTO() и просмотреть структуру и значения КорневойОбъектXDTO. Это позволит убедиться, что все свойства заполнены правильно, коллекции содержат ожидаемое количество элементов, и нет пропущенных обязательных полей.
Особое внимание уделяйте типам данных. Например, если в XSD ожидается xs:dateTime, а вы присваиваете строку, это может вызвать ошибку валидации или некорректную запись.
Работа с XML и XSD в 1С через механизм XDTO предоставляет мощный и гибкий инструмент для интеграции. Понимая основные принципы создания ФабрикиXDTO, интерпретации схемы и заполнения ОбъектовXDTO, мы можем успешно решать задачи по выгрузке данных в сложных форматах XML.