Как из файла XML выгрузить данные в таблицу значений?

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

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

Метод 1: Использование Фабрики XDTO

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

Рассмотрим пример реализации. Важным нюансом здесь является обработка коллекций: если в XML-файле один элемент (например, одна строка товара), XDTO вернет объект. Если элементов несколько — вернется список. Чтобы код не выдавал ошибку, используем вспомогательную функцию.


&НаСервере
Процедура ЗагрузитьИзXML_XDTO(ИмяФайла)
    Чтение = Новый ЧтениеXML;
    Чтение.ОткрытьФайл(ИмяФайла);
    
    // Используем стандартную фабрику
    Попытка
        ОтветXDTO = ФабрикаXDTO.ПрочитатьXML(Чтение);
    Исключение
        Сообщить("Ошибка чтения файла: " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;

    // Предположим, структура файла: Document -> Record
    Для каждого Док ИЗ ПолучитьМассивXDTO(ОтветXDTO.Document) Цикл
        Сообщить("Документ №: " + Док.Number);
        
        Для каждого Запись из ПолучитьМассивXDTO(Док.Record) Цикл
            // Здесь мы можем заполнять таблицу значений
            НоваяСтрока = ТаблицаНоменклатуры.Добавить();
            НоваяСтрока.Артикул = Запись.Barcode;
            НоваяСтрока.Количество = Запись.Quantity;
        КонецЦикла;
    КонецЦикла;
    
    Чтение.Закрыть();
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьМассивXDTO(XDTO_Объект)
    // Функция гарантирует, что мы всегда работаем с коллекцией, 
    // даже если в XML всего один вложенный элемент
    Если ТипЗнч(XDTO_Объект) = Тип("ОбъектXDTO") Тогда
        Массив = Новый Массив;
        Массив.Добавить(XDTO_Объект);
        Возврат Массив;
    Иначе
        Возврат XDTO_Объект; // Это уже коллекция (СписокXDTO)
    КонецЕсли;
КонецФункции

Метод 2: Ручной парсинг через ЧтениеXML

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

Разберем, как правильно организовать цикл обхода и избежать распространенной ошибки с потерей атрибутов. Важно помнить: атрибуты элемента доступны только тогда, когда ТипУзла равен ТипУзлаXML.НачалоЭлемента. Как только вы вызываете метод Прочитать(), чтобы перейти к тексту внутри тега, атрибуты самого тега становятся недоступны.


// Создаем таблицу значений для хранения данных
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("НомерДокумента", Новый ОписаниеТипов("Строка"));
ТЗ.Колонки.Добавить("Вес", Новый ОписаниеТипов("Число"));

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

Пока ЧтениеXML.Прочитать() Цикл
    // Проверяем начало элемента (тега)
    Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
        
        // Если это нужный нам узел "Document", считываем его атрибуты сразу!
        Если ЧтениеXML.Имя = "Document" Тогда
            НовСтр = ТЗ.Добавить();
            
            // Получаем значения атрибутов по именам
            НовСтр.НомерДокумента = ЧтениеXML.ПолучитьАтрибут("Number");
            НовСтр.Вес = Число(ЧтениеXML.ПолучитьАтрибут("TotalGrossWeight"));
            
            // Если атрибутов много, можно перебрать их в цикле
            Пока ЧтениеXML.ПрочитатьАтрибут() Цикл
                ИмяАтрибута = ЧтениеXML.Имя;
                ЗначениеАтрибута = ЧтениеXML.Значение;
                // Обработка...
            КонецЦикла;
        КонецЕсли;
        
    КонецЕсли;
КонецЦикла;

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

Анализ типичной ошибки: Почему атрибут возвращает «Неопределено»?

Проанализируем ситуацию, с которой часто сталкиваются начинающие разработчики. Если вы пытаетесь прочитать атрибут после того, как определили, что тип узла — Текст, система вернет Неопределено. Это происходит потому, что указатель в потоке чтения уже сдвинулся с заголовка тега (где находятся атрибуты) на его содержимое.

Правильная последовательность действий:

  1. Определить ТипУзлаXML.НачалоЭлемента.
  2. Сразу считать все нужные атрибуты через ПолучитьАтрибут() или ПрочитатьАтрибут().
  3. И только после этого переходить к чтению вложенного текста или дочерних узлов.

Метод 3: Стандартные функции БСП

Если в вашей конфигурации используется Библиотека Стандартных Подсистем (БСП), можно воспользоваться готовым инструментом в модуле ОбщегоНазначения. Функция ПрочитатьXMLВТаблицу() предназначена для автоматического разбора XML определенной структуры (обычно той, которую 1С генерирует при выгрузке таблиц).

Рассмотрим, как это вызвать:


// В параметре передается объект ЧтениеXML
ТаблицаРезультат = ОбщегоНазначения.ПрочитатьXMLВТаблицу(ЧтениеXML);

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

Метод 4: Использование построителя DOM

Для файлов среднего размера удобно использовать DOM (Document Object Model). Этот метод загружает всё дерево XML в память, что позволяет легко перемещаться «вверх» и «вниз» по иерархии, а также использовать запросы XPath.


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

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

// Получаем все узлы с именем "Document"
УзлыДокументов = ДокументDOM.ПолучитьЭлементыПоИмени("Document");

Для каждого УзелДокумента Из УзлыДокументов Цикл
    // Чтение атрибутов через карту атрибутов узла
    АтрибутНомер = УзелДокумента.Атрибуты.ПолучитьИмя("Number");
    Если АтрибутНомер <> Неопределено Тогда
        Сообщить(АтрибутНомер.Значение);
    КонецЕсли;
КонецЦикла;

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

Подводя итог, выбор метода зависит от ваших задач. Для интеграции со сторонними сервисами лучше всего подходит Фабрика XDTO. Если же нужно быстро «пробежаться» по огромному файлу и выдернуть пару значений — используйте ЧтениеXML, соблюдая правила работы с указателем узла.

← На главную