Как правильно редактировать XML-файлы и добавлять вложенные элементы через DOM в 1С

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

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

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

Замена атрибутов в существующем XML-файле

Рассмотрим стандартную задачу: нам необходимо найти в XML-файле определенный элемент и изменить значение его атрибута. Например, в файле отчетности нужно заменить идентификатор файла ИдФайл. Многие пытаются сделать это простым текстовым поиском СтрЗаменить, но это небезопасно, так как искомая строка может встретиться в данных, а не в служебных полях.

Правильный подход заключается в использовании объектов ЧтениеXML и ПостроительDOM. Давайте разберем этот процесс по шагам:


// 1. Читаем файл в объектную модель
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ИмяФайла);

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

// 2. Ищем нужные элементы по имени тега
СписокЭлементов = ДокументDOM.ПолучитьЭлементыПоИмени("Файл");

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

Важный нюанс: при записи обновленного документа через ЗаписьXML платформа может автоматически переупорядочить пространства имен (namespaces). Если вы заметили, что вместо xmlns:xsi появилось xmlns:xsd или префиксы поменялись местами — это нормальное поведение парсера. Согласно спецификации XML, порядок атрибутов xmlns и выбор конкретного префикса (если адрес URI совпадает) не влияют на валидность документа.

Добавление сложных вложенных структур (КИЗ и маркировка)

Часто при работе с маркируемыми товарами требуется добавить в существующий блок ДопСведТов новые вложенные теги, например НомСредИдентТов, внутри которого должны располагаться элементы КИЗ.

Типичная ошибка начинающих — пытаться добавить КИЗ как атрибут. Помните: имена атрибутов внутри одного тега должны быть уникальны. Если вам нужно передать список кодов маркировки, это должны быть именно вложенные элементы (теги), а не атрибуты.

Проанализируем правильный алгоритм добавления вложенных узлов:

  1. Находим родительский элемент (например, ДопСведТов).
  2. Создаем новый узел с помощью метода СоздатьЭлемент.
  3. Добавляем его в иерархию через ДобавитьДочерний.
  4. Внутри нового узла аналогично создаем текстовое содержимое или другие подузлы.

Посмотрим на пример реализации, который решает проблему дублирования данных:


// Предположим, мы уже находимся в цикле перебора элементов "ДопСведТов"
Для Каждого Элемент_ДопСведТов Из СписокЭлементов_ДопСведТов Цикл
    
    // Создаем контейнер для кодов маркировки
    УзелНомСред = ДокументDOM.СоздатьЭлемент("НомСредИдентТов");
    Элемент_ДопСведТов.ДобавитьДочерний(УзелНомСред);
    
    // Массив кодов, которые нужно добавить
    МассивКИЗ = ПолучитьСписокКИЗДляТовара(); 
    
    Для Каждого ТекКод Из МассивКИЗ Цикл
        // Создаем элемент КИЗ
        УзелКИЗ = ДокументDOM.СоздатьЭлемент("КИЗ");
        
        // Устанавливаем значение внутри тега <КИЗ>Значение</КИЗ>
        УзелКИЗ.ТекстовоеСодержимое = ТекКод;
        
        // Добавляем КИЗ в родительский узел НомСредИдентТов
        УзелНомСред.ДобавитьДочерний(УзелКИЗ);
    КонецЦикла;
    
КонецЦикла;

Почему нельзя использовать поиск элементов внутри цикла? Встречается ошибка, когда программист после ДобавитьДочерний(НомСредИдентТов) снова вызывает ДокументDOM.ПолучитьЭлементыПоИмени("НомСредИдентТов"). В этом случае поиск вернет все такие элементы в документе, и вы начнете добавлять коды маркировки первого товара во все последующие. Всегда используйте прямую ссылку на созданный объект, которую возвращает метод СоздатьЭлемент.

Нюансы сохранения и кодировки

После внесения всех изменений документ необходимо правильно сохранить. При работе с государственными системами крайне важно соблюдать кодировку (чаще всего это windows-1251). Если использовать настройки по умолчанию, 1С может сохранить файл в UTF-8, что приведет к ошибке при загрузке на портал.

Рассмотрим правильный блок записи:


ЗаписьXML = Новый ЗаписьXML;
// Обязательно указываем кодировку и версию XML
ЗаписьXML.ОткрытьФайл(ИмяФайла, "windows-1251");
ЗаписьXML.ЗаписатьОбъявлениеXML();

ЗаписьDOM = Новый ЗаписьDOM;
ЗаписьDOM.Записать(ДокументDOM, ЗаписьXML);

ЗаписьXML.Закрыть();

Проанализируем ситуацию, когда «обрезается адрес» в пространстве имен. Это может происходить, если вы открыли файл в одной кодировке, а сохраняете в другой, или если в URI содержатся спецсимволы, которые не были экранированы. Используя ЗаписьDOM, мы доверяем платформе 1С формирование корректного XML-синтаксиса, что гораздо надежнее ручной сборки строки.

DOM или СтрЗаменить: что выбрать?

Выясним причину, по которой опытные разработчики предостерегают от использования СтрЗаменить для правки XML:

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

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

← На главную