Как получить XML-текст конкретного узла при чтении XML в 1С?

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

При обмене данными между информационными базами 1С часто возникает задача выгрузить или прочитать не просто значения реквизитов, а сырой исходный текст поддерева XML. Например, требуется сохранить содержимое узла CatalogObject.Справочник1 вместе со всеми его дочерними тегами (Ref, IsFolder, DeletionMark и др.) в виде одной строки.

Объект ЧтениеXML работает как последовательный потоковый парсер. У него отсутствует встроенный метод вроде InnerXML, позволяющий за один вызов получить весь исходный код текущего элемента. Проанализируем несколько способов решения этой задачи в зависимости от объема файла и требуемого быстродействия.

Способ 1. Загрузка в DOM и выгрузка узла в строку

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

Рассмотрим пошагово алгоритм получения строки с помощью объектов ЗаписьDOM и ЗаписьXML:

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

Разберем пример кода на языке 1С:


ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл("C:\Exchange\data.xml");

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

// Поиск узла с помощью XPath
ВыражениеXPath = "//CatalogObject.Справочник1[Ref='a4b8db1c-3cbb-11e4-9445-b4b52f7093b4']";
РезультатXPath = ДокументDOM.ВычислитьВыражениеXPath(ВыражениеXPath);
УзелСправочника = РезультатXPath.ПолучитьСледующий();

Если УзелСправочника <> Неопределено Тогда
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.УстановитьСтроку();
    
    ЗаписьDOM = Новый ЗаписьDOM;
    ЗаписьDOM.Записать(УзелСправочника, ЗаписьXML);
    
    ТекстУзлаXML = ЗаписьXML.Закрыть();
    // Переменная ТекстУзлаXML содержит полное XML-описание элемента
КонецЕсли;

ЧтениеXML.Закрыть();

Способ 2. Частичное считывание в DOM при потоковом чтении

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

Проанализируем реализацию этого подхода:


ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл("C:\Exchange\data.xml");

ПостроительDOM = Новый ПостроительDOM;

Пока ЧтениеXML.Прочитать() Цикл
    Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "CatalogObject.Справочник1" Тогда
        // Считываем только текущий элемент со всеми его дочерними узлами
        УзелDOM = ПостроительDOM.Прочитать(ЧтениеXML);
        
        ЗаписьXML = Новый ЗаписьXML;
        ЗаписьXML.УстановитьСтроку();
        
        ЗаписьDOM = Новый ЗаписьDOM;
        ЗаписьDOM.Записать(УзелDOM, ЗаписьXML);
        
        ТекстУзлаXML = ЗаписьXML.Закрыть();
        Прервать; // Узел получен
    КонецЕсли;
КонецЦикла;

ЧтениеXML.Закрыть();

Способ 3. Использование Фабрики XDTO

Если XML-структура описывает объекты 1С или соответствует стандартной сериализации, для преобразования элемента в строку можно применить ФабрикаXDTO. Когда ЧтениеXML находится на начальном теге объекта, мы считываем его в объект XDTO, а затем записываем обратно в XML-строку.

Рассмотрим пример реализации:


Пока ЧтениеXML.Прочитать() Цикл
    Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "CatalogObject.Справочник1" Тогда
        ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);
        
        ЗаписьXML = Новый ЗаписьXML;
        ЗаписьXML.УстановитьСтроку();
        
        ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ОбъектXDTO);
        ТекстУзлаXML = ЗаписьXML.Закрыть();
        Прервать;
    КонецЕсли;
КонецЦикла;

Выводы и рекомендации

Для небольших XML-файлов проще всего использовать Загрузку в DOM целиком с поиском нужного тега через XPath. Если файл имеет большой объем и нужно сохранить производительность системы, рекомендуется использовать частичное считывание в DOM или Фабрику XDTO прямо в процессе потокового чтения объекта ЧтениеXML.

← На главную