1с преобразовать объектxdto в xml

Обновлено: 04.07.2024

В прошлый раз я выгружал картинки и цены номенклатуры в XML, создавая узлы XML при обходе выборки. Так же создание XML можно переложить на фабрику XDTO. Нам нужно только создать пакет XDTO и добавить в него нужные типы объектов и определить свойства этих типов. После чего выполнить заполнение объекта XDTO данными и записать его в XML. В этом случае нам не нужно контролировать в коде закрытие узлов, после заполнения объекта фабрика сформирует содержимое XML сама.

Доработаем базу из прошлого примера, добавим пакет XDTO и внесем изменения в общий модуль ВыгрузкаПрайса.

Мой пакет XDTO в содержит следующие типы объектов:
- Nomenclature;
- NomenclatureImage;
- PriceString;
- PriceList.


Привожу схему XDTO, при необходимости ее можно подгрузить в свою конфигурацию и посмотреть свойства объектов.

<xs:schema xmlns:tns="http://start1c.blogspot.ru" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://start1c.blogspot.ru" attributeFormDefault="unqualified" elementFormDefault="qualified">
<xs:complexType name="Nomenclature">
<xs:sequence>
<xs:element name="ID" type="xs:string"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="fullName" type="xs:string"/>
<xs:element name="type" type="xs:string"/>
<xs:element name="nomenclatureImage" type="tns:NomenclatureImage" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="NomenclatureImage">
<xs:sequence>
<xs:element name="binImage" type="xs:base64Binary"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="Number_15_2">
<xs:restriction base="xs:decimal">
<xs:minInclusive value="0"/>
<xs:totalDigits value="15"/>
<xs:fractionDigits value="2"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="PriceList">
<xs:sequence>
<xs:element name="priceString" type="tns:PriceString" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="PriceString">
<xs:sequence>
<xs:element name="nomenclature" type="tns:Nomenclature"/>
<xs:element name="price" type="tns:Number_15_2"/>
</xs:sequence>
</xs:complexType>
</xs:schema>

В общий модуль ВыгрузкаПрайса добавляем экспортную функцию ПолучитьДанныеXDTO. Кстати, для приведения различных типов данных к строке необходимого формата здесь используется функция XMLСтрока. Например, данные ссылочного типа представляются в виде строки с уникальным идентификатором этой ссылки, а примитивные типы приводятся к строке с каноническим содержанием.


Теперь в обработке ВыгрузкаПрайса в процедуре Выгрузить поменяем способ выгрузки с ВыгрузкаПрайса.ПолучитьДанныеXML() на ВыгрузкаПрайса.ПолучитьДанныеXDTO() и проверим результат.


Процедура Создание_фабрики_XDTO () Экспорт

// Процедура создает фабрику XDTO (из файла XML) на основе схемы XML

// Создание объект чтения XML (по умолчанию)
XML = Новый ЧтениеXML ;
// Запуск файла XML
XML . ОткрытьФайл ( "D:\Example_XDTO\SсhemaXML.xsd" );

// Создание построителя документа DOM (по умолчанию)
Построитель_DOM = Новый ПостроительDOM ;
// Чтение файла XML (в документ DOM)
Док_DOM = Построитель_DOM . Прочитать ( XML );
// Создание построитель схемы XML (по умолчанию)
ПостроительСхемыXML = Новый ПостроительСхемXML ;
// Получение схемы XML (из документа DOM)
Схема_XML = ПостроительСхемыXML . СоздатьСхемуXML ( Док_DOM );

// Создание набора схем XML (по умолчанию)
Набор_Схем_XML = Новый НаборСхемXML ;
// Добавление схемы XML в набор схем
Набор_Схем_XML . Добавить ( Схема_XML );
// Создание фабрики XDTO на основе набора схем XML
ФабрикаXDTO = Новый ФабрикаXDTO ( Набор_Схем_XML );

Процедура Получение_фабрики_XDTO_из_нескольких_XSD () Экспорт

// Процедура получает фабрики XDTO из нескольких XSD

Схемы_XSD = Новый Массив ;
Схемы_XSD . Добавить ( "D:\Example_XDTO\SсhemaXML_1.xsd" );
Схемы_XSD . Добавить ( "D:\Example_XDTO\SсhemaXML_2.xsd" );
Схемы_XSD . Добавить ( "D:\Example_XDTO\SсhemaXML_3.xsd" );

Пакеты_XSD = Новый Массив ;
Пакеты_XSD . Добавить ( ФабрикаXDTO . Пакеты . Получить ( "URI пакета 1" )); //может быть произвольной
Пакеты_XSD . Добавить ( ФабрикаXDTO . Пакеты . Получить ( "URI пакета 2" )); //может быть произвольной
Пакеты_XSD . Добавить ( ФабрикаXDTO . Пакеты . Получить ( "URI пакета 3" )); //может быть произвольной

Фабрика_XSD = СоздатьФабрикуXDTO ( Схемы_XSD , Пакеты_XSD );

Процедура Создание_значения_XDTO () Экспорт

// Процедура создает новое значение XDTO (немутабельное) с помощью метода Создать()

// Создание значения XDTO из лексического представления
ТипЗначения_XDTO = ГлобФабрикаXDTO . Тип ( "http://www.w3.org/2001/XMLSchema" , "dateTime" );
Значение_XDTO = ГлобФабрикаXDTO . Создать ( ТипЗначения_XDTO , "2021-05-17T11:51:34" );

Процедура Создание_значения_XDTO_файл_XML () Экспорт

// Процедура создает новое значение XDTO (немутабельное) путем чтения файла XML

// Чтение данных значения XDTO (из файла XML)
XML = Новый ЧтениеXML ;
XML . ОткрытьФайл ( "D:/Example_XDTO/Test.xml" ); // обратный слэш!
Значение_XDTO = ГлобФабрикаXDTO . ПрочитатьXML ( XML );

XML = Новый ЗаписьXML ;
XML . ОткрытьФайл ( "D:/Example_XDTO/Test.xml" ); // обратный слэш!

// Запись данных XDTO в файл XML
ГлобФабрикаXDTO = ФабрикаXDTO ;
ГлобФабрикаXDTO . ЗаписатьXML ( XML , Значение_XDTO );

Процедура Создание_объекта_XDTO ( СправочникСсылка ) Экспорт

// Процедура создает новый объект XDTO (мутабельное) с помощью метода Создать()

// Создание пустого объекта XDTO
ТипОбъекта_XDTO = ГлобФабрикаXDTO . Тип ( "http://www.1cnik.by/demo-material" , "Материалы" );
Объект_ХDTO = ГлобФабрикаXDTO . Создать ( ТипОбъекта_XDTO );

// Заполнение его свойств
ОбъектСправочника = СправочникСсылка . ПолучитьОбъект ();
Объект_ХDTO . Наименование = ОбъектСправочника . Наименование ;
Объект_ХDTO . ПолноеНаименование = ОбъектСправочника . ПолноеНаименование ;
Объект_ХDTO . ЕдиницаИзмерения = ОбъектСправочника . ЕдиницаИзмерения ;
Объект_ХDTO . СтранаПроисхождения = ОбъектСправочника . СтранаПроисхождения ;
Объект_ХDTO . КодТНВЭД = ОбъектСправочника . КодТНВЭД ;


Чтение файла в формате XML по порядку (способ №1) в 1С 8.3:

//Подходит для файлов более 100Mb
&НаСервере
Процедура ПрочитатьФайлXMLПоПорядкуСпособ1 ( ПутьКФайлу )

XML = Новый ЧтениеXML ;
XML . ОткрытьФайл ( ПутьКФайлу );

Пока XML . Прочитать () Цикл

Если XML . ТипУзла = ТипУзлаXML . НачалоЭлемента И XML . Имя = "Ресторан" Тогда

Название = XML . ЗначениеАтрибута ( "Название" );
Если Название <> Неопределено Тогда
Сообщить ( "Название ресторана:" + Название );
КонецЕсли;

Категория = XML . ЗначениеАтрибута ( "Категория" );
Если Категория <> Неопределено Тогда
Сообщить ( ". наценочная категория ресторана: " + Категория );
КонецЕсли;

Счет = XML . ЗначениеАтрибута ( "Счет" );
Если Счет <> Неопределено Тогда
Сообщить ( ". средний счет ресторана: " + Счет );
КонецЕсли;

Кухня = XML . ЗначениеАтрибута ( "Кухня" );
Если Кухня <> Неопределено Тогда
Сообщить ( ". кухня ресторана: " + Кухня );
КонецЕсли;

Пока XML . Прочитать () Цикл //

Если XML . ТипУзла = ТипУзлаXML . НачалоЭлемента И XML . Имя = "Меню" Тогда
Сообщить ( "Меню:" );

Пока XML . Прочитать () Цикл //
Если XML . ТипУзла = ТипУзлаXML . НачалоЭлемента И XML . Имя = "Блюдо" Тогда
Название = XML . ЗначениеАтрибута ( "Название" );
Если Название <> Неопределено Тогда
Сообщить ( ". название блюда:" + Название );
КонецЕсли;
ИначеЕсли XML . ТипУзла = ТипУзлаXML . КонецЭлемента И XML . Имя = "Меню" Тогда
Прервать;
КонецЕсли;
КонецЦикла; //

ИначеЕсли XML . ТипУзла = ТипУзлаXML . НачалоЭлемента И XML . Имя = "Описание" Тогда

XML . Прочитать ();
Если XML . ТипУзла = ТипУзлаXML . Текст Тогда
Сообщить ( "Описание:" + XML . Значение );
КонецЕсли;

ИначеЕсли XML . ТипУзла = ТипУзлаXML . КонецЭлемента И XML . Имя = "Ресторан" Тогда

Чтение файла в формате XML по порядку (способ №2) в 1С 8.3:

//Подходит для файлов более 100Mb
&НаСервере
Процедура ПрочитатьФайлXMLПоПорядкуСпособ2 ( ПутьКФайлу )

XML = Новый ЧтениеXML ;
XML . ОткрытьФайл ( ПутьКФайлу );

СписокИмен = Новый СписокЗначений ;

Пока XML . Прочитать () Цикл
Если XML . ТипУзла = ТипУзлаXML . НачалоЭлемента Тогда

СписокИмен . Добавить ( XML . Имя );
ПутьXML = СобратьПуть ( СписокИмен );

Если ПутьXML = "/Рестораны/Ресторан" Тогда
Название = XML . ЗначениеАтрибута ( "Название" );
Если Название <> Неопределено Тогда
Сообщить ( "Название ресторана: " + Название ); //"Китайская грамота"
КонецЕсли;

Категория = XML . ЗначениеАтрибута ( "Категория" );
Если Категория <> Неопределено Тогда
Сообщить ( ". наценочная категория ресторана: " + Категория ); // Высшая
КонецЕсли;

Счет = XML . ЗначениеАтрибута ( "Счет" );
Если Счет <> Неопределено Тогда
Сообщить ( ". средний счет ресторана: " + Счет ); // 3500
КонецЕсли;

Кухня = XML . ЗначениеАтрибута ( "Кухня" );
Если Кухня <> Неопределено Тогда
Сообщить ( ". кухня ресторана: " + Кухня ); // Азиатская
КонецЕсли;

ИначеЕсли ПутьXML = "/Рестораны/Ресторан/Меню" Тогда

ИначеЕсли ПутьXML = "/Рестораны/Ресторан/Меню/Блюдо" Тогда

Название = XML . ЗначениеАтрибута ( "Название" );
Если Название <> Неопределено Тогда
Сообщить ( ". название блюда: " + Название );
КонецЕсли;

ИначеЕсли ПутьXML = "/Рестораны/Ресторан/Описание" Тогда

XML . Прочитать ();
Если XML . ТипУзла = ТипУзлаXML . Текст Тогда
Сообщить ( "Описание: " + XML . Значение );
КонецЕсли;

ИначеЕсли XML . ТипУзла = ТипУзлаXML . КонецЭлемента Тогда

СписокИмен . Удалить ( СписокИмен . Количество () - 1 );

&НаСервере
Функция СобратьПуть ( СписокИмен )

Для Каждого Имя Из СписокИмен Цикл
НашПуть = НашПуть + "/" + Имя ;
КонецЦикла;

Чтение файла в формате XML через document object model (DOM) (способ №3) в 1С 8.3:

//Подходит для файлов менее 100Mb, для больших Не подходит
&НаСервере
Процедура ПрочитатьФайлXMLЧерезDOMСпособ3 ( ПутьКФайлу )

//Поочередная обработка всех узлов документа, представленных в XML:
//1.Объявление механизмов, с помощью которых происходит чтение XML файла; Цикл для обхода узлов;
//2.Считывание данных и атрибутов в узле;
//3.Вывод информации. Если есть необходимость, на этом этапе может происходить запись в переменные или сразу в нужные таблицы;
//4.Завершение работы механизма

ЧтениеXML = Новый ЧтениеXML ;
ЧтениеXML . ОткрытьФайл ( ПутьКФайлу );

Построитель_DOM = Новый ПостроительDOM ;
ДокументXML = Построитель_DOM . Прочитать ( ЧтениеXML );

Для Каждого ТекУзел Из ДокументXML . ЭлементДокумента . ДочерниеУзлы Цикл

Если ТекУзел . ИмяУзла = "Ресторан" Тогда

Название = Ресторан . Атрибуты . ПолучитьИменованныйЭлемент ( "Название" );
Если Название <> Неопределено Тогда
Сообщить ( "Название ресторана:" + Название . Значение ); //"Китайская грамота"
КонецЕсли;

Категория = Ресторан . Атрибуты . ПолучитьИменованныйЭлемент ( "Категория" );
Если Категория <> Неопределено Тогда
Сообщить ( ". наценочная категория ресторана: " + Категория . Значение ); // Высшая
КонецЕсли;

СрСчет = Ресторан . Атрибуты . ПолучитьИменованныйЭлемент ( "Счет" );
Если СрСчет <> Неопределено Тогда
Сообщить ( ". средний счет ресторана: " + СрСчет . Значение ); // 3500
КонецЕсли;

Кухня = Ресторан . Атрибуты . ПолучитьИменованныйЭлемент ( "Кухня" );
Если Кухня <> Неопределено Тогда
Сообщить ( ". кухня ресторана: " + Кухня . Значение ); // Азиатская
КонецЕсли;

Для Каждого ТекУзел1 Из Ресторан . ДочерниеУзлы Цикл

Если ТекУзел1 . ИмяУзла = "Меню" Тогда

Меню = ТекУзел1 ;
Сообщить ( "Меню:" );

Для Каждого ТекУзел2 Из Меню . ДочерниеУзлы Цикл

Если ТекУзел2 . ИмяУзла = "блюдо" Тогда
Блюдо = ТекУзел2 ;

Название = Блюдо . Атрибуты . ПолучитьИменованныйЭлемент ( "Название" );
Если Название <> Неопределено Тогда
Сообщить ( ". название блюда:" + Название . Значение );
КонецЕсли;

ИначеЕсли ТекУзел1 . ИмяУзла = "Описание" Тогда

Сообщить ( "Описание :" + ТекУзел1 . ТекстовоеСодержимое );

&НаКлиенте
Процедура ЗаписатьДанныеВФорматеXML ( ПутьКФайлу )

Рестораны = СоздатьДанныеДляЗаписиВXML ();
ПараметрыЗаписи = Новый ПараметрыЗаписиXML ( "UTF-8" , "1.0" , Ложь); //необязательно их прописовать

XML = Новый ЗаписьXML ;
XML . ОткрытьФайл ( ПутьКФайлу , ПараметрыЗаписи );
XML . ЗаписатьОбъявлениеXML ();
XML . ЗаписатьНачалоЭлемента ( "Рестораны" );

Для Каждого Ресторан Из Рестораны Цикл

XML . ЗаписатьНачалоЭлемента ( "Ресторан" );
XML . ЗаписатьАтрибут ( "Название" , Ресторан . Значение . Название );
XML . ЗаписатьАтрибут ( "Категория" , Ресторан . Значение . Категория );
XML . ЗаписатьАтрибут ( "Счет" , Ресторан . Значение . Счет );
XML . ЗаписатьАтрибут ( "Кухня" , Ресторан . Значение . Кухня );

XML . ЗаписатьНачалоЭлемента ( "Меню" );
Для Каждого БлюдоИзМеню Из Ресторан . Значение . Меню Цикл

XML . ЗаписатьНачалоЭлемента ( "Блюдо" );
XML . ЗаписатьАтрибут ( "Название" , БлюдоИзМеню . Значение . Название );
XML . ЗаписатьКонецЭлемента (); // Блюдо

XML . ЗаписатьКонецЭлемента (); // Меню

XML . ЗаписатьНачалоЭлемента ( "Описание" );
XML . ЗаписатьТекст ( Ресторан . Значение . Описание );
XML . ЗаписатьКонецЭлемента (); // Описание

XML . ЗаписатьКонецЭлемента (); // Ресторан

XML . ЗаписатьКонецЭлемента (); // Рестораны


&НаКлиенте
Функция СоздатьДанныеДляЗаписиВXML ()

Рестораны = Новый СписокЗначений ;

Китайский_ресторан = Новый Структура ( "Название, Категория, Счет, Кухня, Меню, Описание" );
Китайский_ресторан . Название = "Китайская грамота" ;
Китайский_ресторан . Категория = "Высшая" ; //наценочная категория
Китайский_ресторан . Счет = "3500" ; //средний счет
Китайский_ресторан . Кухня = "Азиатская" ;
Китайский_ресторан . Меню = Новый СписокЗначений ;
Китайский_ресторан . Меню . Добавить (Новый Структура ( "Название" , "Суши из форели" ));
Китайский_ресторан . Меню . Добавить (Новый Структура ( "Название" , "Лапша фирменная" ));
Китайский_ресторан . Меню . Добавить (Новый Структура ( "Название" , "Суп из малюсков" ));
Китайский_ресторан . Описание = "Ресторан азиатской кухни Высшей наценочной категории" ;
Рестораны . Добавить ( Китайский_ресторан );

Европейский_ресторан = Новый Структура ( "Название, Категория, Счет, Кухня, Меню, Описание" );
Европейский_ресторан . Название = "Итальянский Экспресс" ;
Европейский_ресторан . Категория = "Люкс" ; //наценочная категория
Европейский_ресторан . Счет = "5000" ; //средний счет
Европейский_ресторан . Кухня = "Европейская" ;
Европейский_ресторан . Меню = Новый СписокЗначений ;
Европейский_ресторан . Меню . Добавить (Новый Структура ( "Название" , "Мясная нарезка из мраморной говядины" ));
Европейский_ресторан . Меню . Добавить (Новый Структура ( "Название" , "Салат де-люкс Комплимент" ));
Европейский_ресторан . Меню . Добавить (Новый Структура ( "Название" , "Пицца от шеф повара" ));
Европейский_ресторан . Описание = "Ресторан европейской кухни категории Люкс" ;
Рестораны . Добавить ( Европейский_ресторан );

В прошлой статье я рассказывал о том, что такое XDTO в 1С, для чего этот механизм нужен и как его использовать.

Сегодня я попробую рассказать о еще одном применении механизма XDTO, а именно об XDTO-сериализации.

Для начала рассмотрим простой случай: предположим у нас есть две конфигурации, и эти две конфигурации имеют одинаковые по структуре объекты, например, справочники (одинаковыми должны быть названия объектов, а также названия, количество и типы реквизитов).

Пример справочника

В этом случае передать данные из одной конфигурации в другую достаточно просто.

тСериализаторXDTO = Новый СериализаторXDTO(ФабрикаXDTO); тСериализаторXDTO.ЗаписатьXML(тЗаписьXML, Справочники.Тест.НайтиПоНаименованию("Тест 1").ПолучитьОбъект(), НазначениеТипаXML.Явное); тСериализаторXDTO = Новый СериализаторXDTO(ФабрикаXDTO);

После сериализации у нас получается вот такой файл:

XDTO-сериализация объекта

XDTO-сериализация объекта

А после десериализации у нас будет ссылка на тот же самый объект в другой конфигурации.

Нужно заметить, что XDTO-сериализации подвергаются не только объекты конфигурации (документы, справочники), но и многие объекты встроенного языка (структуры например):

тСериализаторXDTO = Новый СериализаторXDTO(ФабрикаXDTO); тСериализаторXDTO.ЗаписатьXML(тЗаписьXML, тСтруктура, НазначениеТипаXML.Явное);

XDTO-сериализация объектов встроенного языка

XDTO-сериализация объектов встроенного языка

Если же у нам не нужно сериализировать все реквизиты или в принимающей конфигурации нет копии объекта отдающей конфигурации, то тут работает несколько более сложная схема.

Во-первых нам потребуется XDTO-пакет (или соответствующий XSD-файл) описывающий данные которые мы хотим сериализировать. Для своего справочника я сделал вот такой XDTO-пакет:

XDTO-пакет для сериализации

XDTO-пакет для сериализации

Сама XDTO-сериализация выглядит так:

тНаборСхем = ФабрикаXDTO.ЭкспортСхемыXML("http://1c-programmer-blog.ru/testsr"); тТип = тФабрика.Тип("http://1c-programmer-blog.ru/testsr", "Тест"); ЗаполнитьЗначенияСвойств(тТипXDTO, Справочники.Тест.НайтиПоНаименованию("Тест 1").ПолучитьОбъект());

В коде выше на основании XDTO-пакета создается фабрика, затем тип объекта XDTO, а после этого и сам объект XDTO нужного типа. После заполнения всех нужных свойств, объект записывается в XML-файл:

Выборочная XDTO-сериализация объекта

Выборочная XDTO-сериализация объекта

По очень похожему алгоритму происходит и десериализация объекта:

тНаборСхем = ФабрикаXDTO.ЭкспортСхемыXML("http://1c-programmer-blog.ru/testsr"); тТип = тФабрика.Тип("http://1c-programmer-blog.ru/testsr", "Тест");

На выходе мы получаем объект XDTO со свойствами заполненными из файла, дальше мы можем делать с этим объектом все, что нам нужно.

На этом все, буду рад услышать любые дополнения и замечания.

Если Вы нашли ошибку или неточность, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

(оценок: 3, средняя оценка: 5,00 из 5)

XDTO в 1С

Программное создание диаграммы в 1С 8

Не так давно мне потребовалось сделать отчет и показать график по этому отчету, проблема

Работа с независимым регистром сведений

Достаточно давно я писал о том, как можно быстро очистить регистр сведений, а сегодня

Архивы ZIP в 1С

В этой статье я расскажу о работе с ZIP-архивами в 1С. Для работы с

Здравствуйте! Ваш блог нашла поиском по ошибке, кот возникает в конфигурации Витязь (достроенная БГУ) при загрузке комплекта отчетности.
Если Вы так просто рассказываете о непонятной сериализации, то:
Помогите разобраться что происходит и как выпутаться из этой ситуации!

Вот проблема:
[2016-07-28 12:49:51 (•)]: Начало загрузки существующего объекта.
— Объект: «ф.0503178\стр. 02\гр. 3»
— Метаданные: «Справочник.ОперандыПоказателей»
[EESE0000] [SDXC0200] Объект XDTO ‘/assertionGroup[4]/assertionGroup[1]/assertionDef[63]/operand[2]’ не может быть прочитан.
Модуль: , Номер строки:
причина:

[EESE0000] Поле объекта не обнаружено (СпособыВычисленияПараметровОперандов)
Модуль: Обработка.СериализацияУниверсальнаяОтчетностьМета.МодульОбъекта, Номер строки: 1 514
Модуль: Обработка.ДиспетчерСериализации.МодульОбъекта, Номер строки: 1 042

Читайте также: