Top.Mail.Ru
Заказать консультацию
специалиста 1С
Отправить заявку

Нажимая на кнопку, вы даете согласие на обработку своих персональных данных и соглашаетесь с политикой конфиденциальности.

Выгрузка из 1С в формат XML и простой пример XDTO

Рузавина Наталья Посмотреть все статьи >> Эксперт-разработчик 1С франчайзинговой сети "ИнфоСофт"
10.07.2023
16879
Время прочтения - 10 мин.
Заказать консультацию

В своей работе 1С специалисты часто сталкиваются с выгрузкой из 1С в формат XML. Выгруженные файлы могут использоваться в дальнейшем как для чтения в конфигурациях 1С, так и в других программных продуктах: веб-сервисах, приложениях для работы с отчетностью и т.д.

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

Вначале мы рассмотрим выгрузку документа из 1С в XML базовыми средствами выгрузки:

  • Пример 1 – выгрузка документа полностью;

  • Пример 2 - выгрузка «по частям».

Затем выгрузим то же самое средствами XDTO:

  • Пример 3 – использование глобальной фабрики XDTO без создания пакета XDTO;

  • Пример 4 – использование пакета XDTO;

  • Пример 5 – считывание схемы XDTO из файла.

Все примеры можно посмотреть в обработке Примеры выгрузки XDTO в демонстрационной базе.

1.png

Создадим пустую конфигурацию и в ней документ Начисление зарплаты. С целью упрощения примера не будем заводить другие объекты в конфигурации и заниматься задачами расчета и проведения документа. У документа заведем реквизиты - Подразделение (ссылка на справочник Подразделения), РасчетАванса (булево), СуммаДокумента (число) и табличную часть Сотрудники со ссылкой на справочник Сотрудники и суммой.

 2.png

 

Создадим и заполним один документ. Поставим задачу выгрузить его данные в xml.

3.png

 

Вопрос 1:

Можно ли выгрузить данные в XML без использования XDTO?

Ответ 1:

Да. Можно использовать базовые средства записи Xml.


Пример 1. Выгрузка всего документа базовыми средствами xml

Файл = Новый ЗаписьXML;      //создали новую запись
  Файл.ОткрытьФайл(ИмяФайлаXML); //открыли файл для записи по адресу ИмяФайлаXML
     Файл.ЗаписатьОбъявлениеXML(); //Записали директиву, объявление файла XML, в начале файла создастся текст вида <?xml version="1.0"?>
  ДокументОбъект = ДокСсылка.ПолучитьОбъект();
                     ЗаписатьXML(Файл, ДокументОбъект, НазначениеТипаXML.Явное);//записали полностью документ
                     Файл.Закрыть();

 

Метод ЗаписатьXML() выгружает объект полностью, при этом сам определяет структуру выгружаемого объекта, и в результат добавляются некоторые служебные поля (такие как пометка удаления DeletionMark, признак проведения Posted).

Результат выгрузки:

4.png 


 Пример 2. «Ручная» выгрузка документа базовыми средствами xml

На практике объект не всегда нужно выгружать полностью, поэтому рассмотрим выгрузку документа с «ручным» перебором его реквизитов с различными типами данных, а также строк табличной части. Для сериализации, то есть, преобразования любого типа данных в строку - будем пользоваться Функцией XMLСтрока(). Для ссылочного типа результатом преобразования будет уникальный идентификатор.

    

  //начало корневого элемента
      Файл.ЗаписатьНачалоЭлемента("НачислениеЗарплаты");
            //Далее пользуемся Сериализацией - для преобразования любого типа в строку. Для ссылочного типа это будет уникальный идентификатор.
      //Пользуемся для этого функцией XMLСтрока()
      // Записать значение типа Дата.
            ТипXML = XMLТипЗнч(ДокСсылка.Дата);
            Файл.ЗаписатьНачалоЭлемента("Дата");
            //или так:
      //Файл.ЗаписатьНачалоЭлемента(ТипXML.ИмяТипа, ТипXML.URIПространстваИмен);
            Файл.ЗаписатьТекст(XMLСтрока(ДокСсылка.Дата));
            Файл.ЗаписатьКонецЭлемента();
            // Записать значение типа Строка.
            ТипXML = XMLТипЗнч(ДокСсылка.Номер);
            Файл.ЗаписатьНачалоЭлемента("Номер");
            Файл.ЗаписатьТекст(XMLСтрока(ДокСсылка.Номер));
            Файл.ЗаписатьКонецЭлемента();
            // Получить ссылку на справочник
            Файл.ЗаписатьНачалоЭлемента("Подразделение");  
            СсылкаНаПодразделение = ДокСсылка.Подразделение;
            ТипXML = XMLТипЗнч(СсылкаНаПодразделение);
            Файл.ЗаписатьНачалоЭлемента("Ссылка");
            Файл.ЗаписатьТекст(XMLСтрока(СсылкаНаПодразделение));
            Файл.ЗаписатьКонецЭлемента();
            Файл.ЗаписатьНачалоЭлемента("Наименование");
            Файл.ЗаписатьТекст(СсылкаНаПодразделение.Наименование);
            Файл.ЗаписатьКонецЭлемента();
            Файл.ЗаписатьКонецЭлемента();    //подразделение
            // Записать значение типа Число.
            // Получить значение "ТипДанныхXML" для числа.
            ТипXML = XMLТипЗнч(ДокСсылка.СуммаДокумента);
            Файл.ЗаписатьНачалоЭлемента("СуммаДокумента");
            Файл.ЗаписатьТекст(XMLСтрока(ДокСсылка.СуммаДокумента));
            Файл.ЗаписатьКонецЭлемента();
                  // Записать значение типа Булево
            ТипXML = XMLТипЗнч(ДокСсылка.РасчетАванса);
            Файл.ЗаписатьНачалоЭлемента("РасчетАванса");
            Файл.ЗаписатьТекст(XMLСтрока(ДокСсылка.РасчетАванса));
            Файл.ЗаписатьКонецЭлемента();
                  //универсальная выгрузка табличных частей
      Для Каждого ТЧ из ДокСсылка.Метаданные().ТабличныеЧасти Цикл
                                                        Файл.ЗаписатьНачалоЭлемента("ТабличнаяЧасть");
                                                        Файл.ЗаписатьАтрибут("Имя", ТЧ.Имя);
                                                        Для Каждого СтрокаТЧ из ДокСсылка[ТЧ.Имя] Цикл
                                                                                      Файл.ЗаписатьНачалоЭлемента("ЭлементКоллекции");
                                                                                                  Для Каждого РеквизитТЧ Из ТЧ.Реквизиты Цикл
                                                                                                                              Файл.ЗаписатьНачалоЭлемента("Реквизит");
                                                                                                                             Файл.ЗаписатьАтрибут("Имя", РеквизитТЧ.Имя);
                                                                                                                              ТипЗначения = ТипЗнч(СтрокаТЧ[РеквизитТЧ.Имя]);
                                                                                                                             Если Не ТипЗначения = Тип("Неопределено") Тогда
                                                                                                                                                       Файл.ЗаписатьАтрибут("ИмяТипа", XMLТип(ТипЗначения).ИмяТипа);
                                                                                                                                                        Файл.ЗаписатьАтрибут("URI", XMLТип(ТипЗначения).URIПространстваИмен);
                                                                                                                                                    КонецЕсли;
                                                                                                                             Файл.ЗаписатьТекст(XMLСтрока(СтрокаТЧ[РеквизитТЧ.Имя]));
                                                                                                                             Файл.ЗаписатьКонецЭлемента();
                                                                                                                       КонецЦикла;
                                                                             Файл.ЗаписатьКонецЭлемента();
                                                                             КонецЦикла;
                                                        Файл.ЗаписатьКонецЭлемента();
                                  КонецЦикла;
      //
            Файл.ЗаписатьКонецЭлемента(); //начисление зарплаты

 

Результат выгрузки:

5.png


Вопрос 2:

Зачем нужен механизм XDTO?

Ответ 2:

Механизм XDTO создан для оперирования структурой XML. Если известна схема XDTO для XML-документа, то возможно обращаться к фрагментам этого документа «через точку», как к реквизитам объектов конфигурации, а не записывать их как отдельные блоки xml-файла.

XDTO-пакет – объект конфигурации, который предназначен для описания значений, типов, их взаимосвязей. С помощью команд экспорта и импорта пакет можно выгрузить в файл *.xsd (xml-схема) и загрузить в конфигурацию готовую схему. Пространство имен — свойство XDTO-пакета — часто задается в формате веб-адреса, что дезориентирует программистов, начинающих знакомиться с этим объектом. В действительности это просто принятый формат и строка может быть любой с учетом соблюдения уникальности внутри конфигурации.

Помимо пакетов, создаваемых программистами в конфигураторе (ветка XDTO-пакеты дерева метаданных), существуют стандартные пакеты, описывающих все данные, предоставляемые платформой. Пакет http://v8.1c.ru/8.1/data/enterprise/current-config содержит в себе все метаданные текущей конфигурации. Пакет http://www.w3.org/2001/XMLSchema содержит стандартные типы xml, такие как число или строка.

Фабрика XDTO – это объект встроенного языка 1С, который позволяет создавать объекты XDTO нужного типа. Глобальная фабрика, доступная через свойство глобального контекста ФабрикаXDTO, содержит все встроенные пакеты и пакеты, созданные разработчиками.

 

Подпишитесь на дайджест!
Подпишитесь на дайджест, и получайте ежемесячно подборку полезных статей.

Нажимая на кнопку, вы даете согласие на обработку своих персональных данных и соглашаетесь с политикой конфиденциальности.

Пример 3. Выгрузка через глобальную фабрику XDTO

Выгрузим документ, используя глобальную фабрику XDTO и пакет http://v8.1c.ru/8.1/data/enterprise/current-config с метаданными текущей конфигурации. При этом для свойств документа используем английский синтаксис, к документу-объекту обращаемся как к DocumentObject.ИмяДокумента, к справочнику-объекту как к CatalogObject.ИмяСправочника, к табличной части документа - как DocumentTabularSectionRow.ИмяДокумента.ИмяТабличнойЧасти.

Теперь возможно обращение «через точку», например, к подразделению в шапке документа.      

6.png

                    

   ТипОбъектаXDTOПодразделение = ФабрикаXDTO.Тип("http://v8.1c.ru/8.1/data/enterprise/current-config", "CatalogObject.Подразделения");
      ПодразделениеXDTO = ФабрикаXDTO.Создать(ТипОбъектаXDTOПодразделение);
   ПодразделениеXDTO.Ref = СериализаторXDTO.XMLСтрока(ДокСсылка.Подразделение);
   ПодразделениеXDTO.Code = ДокСсылка.Подразделение.Код;
   ПодразделениеXDTO.Description = ДокСсылка.Подразделение.Наименование;
      ТипОбъектаXDTOДокумент = ФабрикаXDTO.Тип("http://v8.1c.ru/8.1/data/enterprise/current-config", "DocumentObject.НачислениеЗарплаты");
      ДокументХDTO = ФабрикаXDTO.Создать(ТипОбъектаXDTOДокумент);
   ДокументХDTO.Ref = СериализаторXDTO.XMLСтрока(ДокСсылка);
   ДокументХDTO.Date = ДокСсылка.Дата;
   ДокументХDTO.Number = ДокСсылка.Номер;
   ДокументХDTO.Подразделение = ПодразделениеXDTO.Ref; //обращение через точку
         Для Каждого СтрокаНачисления Из ДокСсылка.Начисления Цикл
                                          ТипОбъектаXDTOСотрудник = ФабрикаXDTO.Тип("http://v8.1c.ru/8.1/data/enterprise/current-config", "CatalogObject.Сотрудники");
                                          СотрудникXDTO = ФабрикаXDTO.Создать(ТипОбъектаXDTOСотрудник);
                     СотрудникXDTO.Ref = СериализаторXDTO.XMLСтрока(СтрокаНачисления.Сотрудник);
                     СотрудникXDTO.Code = СтрокаНачисления.Сотрудник.Код;
                     СотрудникXDTO.Description = СтрокаНачисления.Сотрудник.Наименование;
                                          ТипОбъектаXDTOТабличнаяЧасть = ФабрикаXDTO.Тип("http://v8.1c.ru/8.1/data/enterprise/current-config", "DocumentTabularSectionRow.НачислениеЗарплаты.Начисления");
                                          СтрокаНачисленияXDTO = ФабрикаXDTO.Создать(ТипОбъектаXDTOТабличнаяЧасть);
                     СтрокаНачисленияXDTO.Сотрудник = СотрудникXDTO.Ref;
                     СтрокаНачисленияXDTO.Сумма = СтрокаНачисления.Сумма;
                                          ДокументХDTO.Начисления.Добавить(СтрокаНачисленияXDTO);
                        КонецЦикла;
         ФабрикаXDTO.ЗаписатьXML(НоваяЗаписьXML,ДокументХDTO);

  

 

Результат выгрузки:

7.png


Пример 4. Выгрузка документа через XDTO-пакет

В предыдущем примере мы использовали глобальную фабрику XDTO, не создавая отдельный пакет XDTO. Но средствами языка 1С возможно создавать новые фабрики, включая в них только типы из нужных пакетов. В рабочей ситуации использование пакета XDTO применяется, например, в случае необходимости выгрузки данных отчетности в определенном формате, «зашифрованном» в предоставленном файле *.xsd, который можно загрузить в конфигурацию как XDTO-пакет.

Выгрузим наш документ с помощью ручного создания пакета XDTO. Добавим в дерево конфигурации пакет ИнфоСофт с пространством имен www.infosoft.ru (что, как мы помним, не является веб-ссылкой. Можно было использовать просто имя infosoft или другое).

8.png9.png

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

Для простых типов выберем типы из пакета http://www.w3.org/2001/XMLSchema, для «ссылочных» типов, в частности, свойства Подразделение типа Начисление зарплаты выберем ссылку на тип Подразделение из пакета ИнфоСофт.

Для табличной части поставим Тип — СтрокаТабличнойЧасти из того же пространства имен, максимальное количество = -1 (неограничено).

10.png

ПодразделениеXDTO = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("www.infosoft.ru", "Подразделение"));
   ПодразделениеXDTO.Ссылка = СериализаторXDTO.XMLСтрока(ДокСсылка.Подразделение);
   ПодразделениеXDTO.Код = ДокСсылка.Подразделение.Код;
   ПодразделениеXDTO.Наименование = ДокСсылка.Подразделение.Наименование;
         ДокументХDTO = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("www.infosoft.ru", "НачислениеЗарплаты"));
      ДокументХDTO.Ссылка = СериализаторXDTO.XMLСтрока(ДокСсылка);
   ДокументХDTO.Дата = ДокСсылка.Дата;
   ДокументХDTO.Номер = ДокСсылка.Номер;
   ДокументХDTO.Подразделение = ПодразделениеXDTO;
   ДокументХDTO.СуммаДокумента = ДокСсылка.СуммаДокумента;
   ДокументХDTO.РасчетАванса = ДокСсылка.РасчетАванса;
            Для Каждого СтрокаНачисления Из ДокСсылка.Начисления Цикл
                                          СотрудникXDTO = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("www.infosoft.ru", "Сотрудник"));
                     СотрудникXDTO.Ссылка = СериализаторXDTO.XMLСтрока(СтрокаНачисления.Сотрудник);
                     СотрудникXDTO.Код = СтрокаНачисления.Сотрудник.Код;
                     СотрудникXDTO.Наименование = СтрокаНачисления.Сотрудник.Наименование;
                                          СтрокаНачисленияXDTO = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("www.infosoft.ru", "СтрокаТабличнойЧасти"));
                     СтрокаНачисленияXDTO.Сотрудник = СотрудникXDTO;
                     СтрокаНачисленияXDTO.Сумма = СтрокаНачисления.Сумма;
                                          ДокументХDTO.ТабличнаяЧастьНачисления.Добавить(СтрокаНачисленияXDTO);
                        КонецЦикла;
         ФабрикаXDTO.ЗаписатьXML(Файл,ДокументХDTO);

           

Результат выгрузки:

11.png


Вопрос 3: 

Нужно ли изменять конфигурацию для работы XDTO?

Ответ 3:

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

  

Пример 5. Хранение схемы XDTO в файле

Сохраним схему ИнфоСофт в файл Схема.xsd в нашем каталоге выгрузки.

Создадим фабрику XDTO на основе схемы XML, содержащейся в файле.

                // Создать фабрику XDTO на основе схемы XML, содержащейся в файле XML
                     // Создать объект чтения XML по умолчанию
                     ЧтениеXML = Новый ЧтениеXML;
                     // Открыть файл XML
                     ЧтениеXML.ОткрытьФайл(КаталогВыгрузки+"\схема.xsd");
                     // Создать построитель документа DOM по умолчанию
                     ПостроительDOM = Новый ПостроительDOM;
                     // Прочитать файл XML в документ DOM
                     ДокументDOM = ПостроительDOM.Прочитать(ЧтениеXML);
                     // Создать построитель схемы XML по умолчанию
                     ПостроительСхемыXML = Новый ПостроительСхемXML;
                     // Получить схему XML из документа DOM
                     СхемаXML = ПостроительСхемыXML.СоздатьСхемуXML(ДокументDOM);
                     // Создать набор схем XML по умолчанию
                     НаборСхемXML = Новый НаборСхемXML;
                     // Добавить схему XML в набор схем XML
                     НаборСхемXML.Добавить(СхемаXML);
                     // Создать фабрику XDTO на основе набора схем XML
                     НоваяФабрикаXDTO = Новый ФабрикаXDTO(НаборСхемXML);

 

Далее код идентичен Примеру 4 с заменой ФабрикаXDTO на НоваяФабрикаXDTO.

Для чистоты эксперимента можно удалить из конфигурации XDTO пакет ИнфоСофт, выгрузка будет работать.

 

Вопрос 4:

Можно ли «нарисовать» схему XDTO не в 1С, а в каком-нибудь редакторе?

Ответ 4:

Да, существует, например, программа Liquid XML Studio, а также онлайн-сервисы.

 

Вопрос 5:

Что делать, если есть xml, но нет схемы к нему?

 Ответ 5:

Существует множество инструментов, как онлайн так и оффлайн, способных по входящему XML-файлу распознать его структуру и вывести в формате XSD. Например, xsd.exe, являющийся частью NET Framework (отдельно файл удалось найти по адресу https://juliankay.com/development/download-xsd-exe) или бесплатный онлайн-конвертер https://www.liquid-technologies.com/online-xml-to-xsd-converter

Результат автоматического распознавания, скорее всего, потребует ручных правок.

 

Мы выгрузили в XML один документ различными способами, как с XDTO, так и без. Результирующие файлы немного отличаются форматом, но в выгрузку попали все имеющиеся поля документа. В заключение статьи сделаем следующие выводы:

1) XDTO можно использовать как инструмент выгрузки в XML-формат

2) Использовать именно XDTO для XML необязательно, но может быть удобно или необходимо (например, при обмене с другими приложениями в случае имеющегося файла со схемой *.xsd)

3) Работа с XDTO необязательно подразумевает изменение конфигурации и добавление XDTO-пакета.

Напомним, что все примеры,
приведенные в статье, находятся в приложенной тестовой базе в обработке Примеры
выгрузки в XML.


Заказать консультацию специалиста 1С
Оставьте заявку и наши эксперты проконсультируют вас по данной статье.
Отправить заявку

Нажимая на кнопку, вы даете согласие на обработку своих персональных данных и соглашаетесь с политикой конфиденциальности.

Рассказать друзьям
Для разработчиков 1С
Вам может быть интересно: