Как в 1С сформировать XML-файл со вложенными элементами («лесенкой»), а не атрибутами в одну строку?

Программист
← На главную

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

Анализ проблемы: Атрибуты или вложенные элементы?

Давайте сначала проясним разницу. Когда мы говорим об атрибутах, мы имеем в виду структуру вида:

<Offer NameOffer="Стол письменный" VendorCode="СП-001" Group="Мебель офисная" />

Здесь NameOffer, VendorCode и Group — это атрибуты элемента Offer. Они записываются внутри открывающего тега и располагаются в одну строку. Для их создания используется метод ЗаписатьАтрибут.

Однако часто требуется другая структура — с вложенными элементами (или дочерними узлами), которую называют "лесенкой":


<Offer>
    <NameOffer>Стол письменный</NameOffer>
    <VendorCode>СП-001</VendorCode>
    <Group>Мебель офисная</Group>
</Offer>

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

Решение: Создание иерархической структуры с помощью ЗаписатьНачалоЭлемента

Ключ к решению — в правильном использовании методов объекта ЗаписьXML. Вместо того чтобы добавлять множество атрибутов к одному элементу, нам нужно для каждого реквизита создать свою пару открывающего и закрывающего тегов. Для этого используются методы ЗаписатьНачалоЭлемента() и ЗаписатьКонецЭлемента().

Рассмотрим два практических способа реализации.

Вариант 1: Вложенный элемент с атрибутом

Этот способ предполагает, что для каждого реквизита мы создаем новый элемент, а само значение помещаем в его атрибут, например, с именем "Значение".

Пример кода:


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

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

ЗаписьXML.ЗаписатьКонецЭлемента; // Закрываем "Товар"

Результат в XML-файле будет выглядеть так:


<Товар>
    <Наименование Значение="Солянка" />
    <Артикул Значение="1111111" />
</Товар>

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

Вариант 2: Вложенный элемент с текстовым содержимым (рекомендуемый)

Это более классический и семантически верный способ. Имя реквизита становится именем тега, а его значение — текстовым содержимым этого тега. Для записи значения используется метод ЗаписатьТекст().

Пример кода:


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

    // Реквизит "Наименование"
    ЗаписьXML.ЗаписатьНачалоЭлемента("Наименование");
    ЗаписьXML.ЗаписатьТекст("Солянка");
    ЗаписьXML.ЗаписатьКонецЭлемента; // Закрываем "Наименование"
    
    // Реквизит "Артикул"
    ЗаписьXML.ЗаписатьНачалоЭлемента("Артикул");
    ЗаписьXML.ЗаписатьТекст("1111111");
    ЗаписьXML.ЗаписатьКонецЭлемента; // Закрываем "Артикул"
    
ЗаписьXML.ЗаписатьКонецЭлемента; // Закрываем "Товар"

Результат в XML-файле:


<Товар>
    <Наименование>Солянка</Наименование>
    <Артикул>1111111</Артикул>
</Товар>

Этот вариант является предпочтительным в большинстве случаев, так как он четко разделяет имя поля (тег) и его значение (текст).

Итоговый рабочий пример кода

Рассмотрим полный пример кода, который решает исходную задачу. В нем используется первый из рассмотренных вариантов (вложенный элемент с атрибутом), но его легко можно адаптировать под второй вариант с помощью ЗаписатьТекст().

В этом коде производится обход табличной части Объект.КаталогНСИ и для каждой строки номенклатуры создается элемент Offer со вложенными элементами для каждого реквизита.


Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
Диалог.Фильтр = "XML (*.XML)|*.XML|";

Если Диалог.Выбрать() Тогда
    ИмяФайла = Диалог.ПолноеИмяФайла;
    
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.ОткрытьФайл(ИмяФайла);
    ЗаписьXML.ЗаписатьОбъявлениеXML();
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("Offers"); // Корневой элемент
    
    Для Каждого ЭлементНоменклатуры Из Объект.КаталогНСИ Цикл
        
        ЗаписьXML.ЗаписатьНачалоЭлемента("Offer"); // Элемент для одной номенклатуры
        
        // Вложенный элемент для Наименования
        ЗаписьXML.ЗаписатьНачалоЭлемента("NameOffer");
        ЗаписьXML.ЗаписатьАтрибут("NameOffer", Строка(ЭлементНоменклатуры.Наименование));
        ЗаписьXML.ЗаписатьКонецЭлемента();
        
        // Вложенный элемент для Артикула
        ЗаписьXML.ЗаписатьНачалоЭлемента("VendorCode");
        ЗаписьXML.ЗаписатьАтрибут("VendorCode", Строка(ЭлементНоменклатуры.Артикул));
        ЗаписьXML.ЗаписатьКонецЭлемента();
        
        // Вложенный элемент для Группы
        ЗаписьXML.ЗаписатьНачалоЭлемента("Group");
        ЗаписьXML.ЗаписатьАтрибут("Group", Строка(ЭлементНоменклатуры.ГруппаНоменклатуры));
        ЗаписьXML.ЗаписатьКонецЭлемента();
        
        // Вложенный элемент для Характеристики
        ЗаписьXML.ЗаписатьНачалоЭлемента("Characteristic");
        ЗаписьXML.ЗаписатьАтрибут("Characteristic", Строка(ЭлементНоменклатуры.ХарактеристикаНом));
        ЗаписьXML.ЗаписатьКонецЭлемента();
        
        ЗаписьXML.ЗаписатьКонецЭлемента(); // Закрываем "Offer"
        
    КонецЦикла;
    
    ЗаписьXML.ЗаписатьКонецЭлемента(); // Закрываем "Offers"
    ЗаписьXML.Закрыть();
    
КонецЕсли;

Главный вывод: чтобы управлять структурой XML-файла и выводить данные "лесенкой", необходимо активно использовать связку методов ЗаписьXML.ЗаписатьНачалоЭлемента() и ЗаписьXML.ЗаписатьКонецЭлемента() для каждого реквизита, а значение помещать внутрь с помощью ЗаписьXML.ЗаписатьТекст() или как атрибут вложенного элемента.

← На главную