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

Программист 1С v8.3 (Управляемые формы) Управленческий учет Торговля и дистрибуция
← На главную

Работа с XML — одна из наиболее частых задач при интеграции 1С с внешними системами, особенно в контексте электронного документооборота (ЭДО) и маркировки товаров «Честный Знак». Часто возникает ситуация, когда существующий XML-файл (например, УПД) нужно не просто прочитать, а модифицировать: добавить сведения о кодах маркировки, изменить идентификаторы или вставить дополнительные информационные поля. В этой статье мы подробно разберем, как правильно добавлять новые узлы и строки в XML, используя различные механизмы платформы 1С:Предприятие.

Постановка задачи

Представим ситуацию: у нас есть готовый XML-файл формата УПД. Нам необходимо выполнить три операции:

  1. Изменить значение атрибута ИдФайл в заголовке документа.
  2. Добавить новый элемент ИнфПолФХЖ2 с атрибутами GTIN сразу после аналогичных информационных полей.
  3. Преобразовать простой элемент ДопСведТов, который изначально выглядит как <ДопСведТов КодТов="00-00" />, в сложную структуру с вложенными узлами НомСредИдентТов и списком КИЗ.

Метод 1: Использование объектной модели документа (DOM)

Метод DOM (Document Object Model) удобен тем, что загружает весь XML-файл в память в виде дерева объектов. Это позволяет нам свободно перемещаться по узлам, искать элементы по имени и изменять их структуру. Рассмотрим, как реализовать наши задачи этим способом.

Шаг 1: Чтение и подготовка документа. Сначала нам нужно прочитать файл и инициализировать построитель DOM.


ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ИмяВременногоФайла);

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

Шаг 2: Изменение атрибутов. Проанализируем ситуацию, когда нам нужно найти конкретный узел и обновить его атрибут. Для этого используется метод УстановитьАтрибут().


СписокЭлементовDOMФайл = ДокументDOM.ПолучитьЭлементыПоИмени("Файл");
Для Каждого ЭлементDOM Из СписокЭлементовDOMФайл Цикл
    Если ЭлементDOM.ЕстьАтрибут("ИдФайл") Тогда
        СтароеЗначение = ЭлементDOM.ПолучитьАтрибут("ИдФайл");
        НовоеЗначение = СтрЗаменить(СтароеЗначение, "_0_0_0_0_0_00", "_0_1_0_0_0_00");
        ЭлементDOM.УстановитьАтрибут("ИдФайл", НовоеЗначение);
    КонецЕсли;
КонецЦикла;

Шаг 3: Добавление новых вложенных элементов. Это самая важная часть. Чтобы превратить пустой тег в контейнер с вложенными строками, мы должны создать новые элементы через ДокументDOM.СоздатьЭлемент() и добавить их в иерархию методом ДобавитьДочерний().

Выясним причину, по которой у автора вопроса не получалось добавить строки: он пытался использовать УстановитьАтрибут() для вставки целых объектов, в то время как атрибут — это просто текстовая пара "ключ-значение". Правильный подход выглядит так:


СписокЭлементовDOMДопСведТов = ДокументDOM.ПолучитьЭлементыПоИмени("ДопСведТов");
Для Каждого ЭлементDOM Из СписокЭлементовDOMДопСведТов Цикл
    АтрибутКод = ЭлементDOM.ПолучитьАтрибут("КодТов");
    
    // 1. Добавляем ИнфПолФХЖ2 (GTIN)
    НовоеПоло = ДокументDOM.СоздатьЭлемент("ИнфПолФХЖ2");
    НовоеПоло.УстановитьАтрибут("Идентиф", "GTIN");
    НовоеПоло.УстановитьАтрибут("Значен", "04600000000000");
    // Вставляем в родительский элемент
    ЭлементDOM.ДобавитьДочерний(НовоеПоло);
    
    // 2. Создаем структуру маркировки КИЗ
    МассивКИЗ = НайтиKIZ(АтрибутКод); // Функция получения данных
    
    Если МассивКИЗ.Количество() > 0 Тогда
        УзелНомСредИдент = ДокументDOM.СоздатьЭлемент("НомСредИдентТов");
        
        Для Каждого ТекКИЗ Из МассивКИЗ Цикл
            УзелКИЗ = ДокументDOM.СоздатьЭлемент("КИЗ");
            // Добавляем текстовое содержимое внутрь тега КИЗ
            ТекстКИЗ = ДокументDOM.СоздатьТекст(ТекКИЗ);
            УзелКИЗ.ДобавитьДочерний(ТекстКИЗ);
            
            // Добавляем КИЗ внутрь НомСредИдентТов
            УзелНомСредИдент.ДобавитьДочерний(УзелКИЗ);
        КонецЦикла;
        
        // Добавляем всю структуру в ДопСведТов
        ЭлементDOM.ДобавитьДочерний(УзелНомСредИдент);
    КонецЕсли;
КонецЦикла;

Важный нюанс: Обратите внимание, что при добавлении дочерних узлов в элемент <ДопСведТов />, платформа при записи автоматически уберет закрывающий слеш в начале и добавит полноценный закрывающий тег </ДопСведТов>. Программисту не нужно делать это вручную.

Метод 2: Работа через XDTO (Сериализация)

Проанализируем более продвинутый метод — использование фабрики XDTO. Этот способ является наиболее правильным при работе с регламентированными форматами (ФНС, ЭДО), так как он гарантирует валидность документа согласно схеме (XSD).

Рассмотрим по шагам, как модифицировать документ через XDTO:

  1. Загружаем XML-файл в объект XDTO, используя соответствующий пакет из конфигурации (например, ON_NSCHFDOPPR).
  2. Находим нужную коллекцию строк (обычно это свойство СостТабл или ДопСведТов).
  3. Создаем новые объекты XDTO с помощью ФабрикаXDTO.Создать().
  4. Добавляем созданные объекты в список (коллекцию).
  5. Записываем объект XDTO обратно в XML.

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

Проблема пространств имен (Namespaces)

В сообщениях форума упоминалось, что при перезаписи файла через DOM меняются префиксы пространств имен (например, xmlns:xsi превращается в xmlns:xsd). Рассмотрим, почему это происходит. Построитель DOM при чтении может переопределять пространства имен, если они не зафиксированы жестко.

Чтобы избежать этой проблемы и сохранить оригинальное оформление шапки XML, рекомендуется использовать методы с поддержкой пространств имен, такие как СоздатьЭлементNS(), или настраивать параметры ЗаписьXML. Если же строгая идентичность префиксов критична для принимающей стороны, иногда проще использовать комбинированный метод: последовательное чтение ЧтениеXML и запись в новый файл через ЗаписьXML, вставляя нужные блоки кода «на лету» в момент прохождения соответствующих узлов. Для решения этой задачи можно использовать обработку для замены данных в XML-файле.

Заключение

Мы разобрали основные подходы к модификации XML в 1С. Для простых задач и небольших файлов идеально подходит DOM, так как он позволяет точечно изменять структуру документа. Для работы с большими файлами лучше использовать потоковую запись (ЧтениеXML + ЗаписьXML). Если же требуется строгая проверка на соответствие государственным стандартам, лучшим выбором будет XDTO. Для разового визуального изменения структуры документа подойдёт обработка для чтения и редактирования XML-файлов.

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

← На главную