Как правильно парсить XML в 1С: различие между атрибутами и тегами и получение их значений

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

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

В чем разница между атрибутом и узлом (тегом) XML

Для понимания логики работы парсера проанализируем структуру типовой XML-записи:


<offer id="1001" available="true">
    <vendorCode>ART-12345</vendorCode>
    <picture>http://example.com/image.jpg</picture>
    <param name="Мощность" unit="кВт">2.2</param>
</offer>

Разберем основные элементы этой структуры:

  1. Имя элемента (тег) — это названия узлов, такие как offer, vendorCode, picture и param.
  2. Атрибуты элемента — это свойства, записанные внутри самого открывающего тега через знак равенства. В примере выше id="1001" и available="true" — это атрибуты тега offer, а name="Мощность" и unit="кВт" — атрибуты тега param.
  3. Текстовое значение (контент) — это содержимое, расположенное между открывающим и закрывающим тегами. Значения ART-12345 и http://example.com/image.jpg являются не атрибутами, а дочерними текстовыми узлами (ТипУзлаXML.Текст).

Таким образом, попытка вызвать метод ПолучитьАтрибут("vendorCode") у элемента offer или picture возвращает Неопределено, потому что vendorCode не записан внутри заголовка тега как атрибут.

Способ 1. Потоковое чтение с помощью объекта ЧтениеXML

Объект ЧтениеXML осуществляет последовательный обход документа. Когда парсер находится на узле ТипУзлаXML.НачалоЭлемента с именем vendorCode, его текстовое содержимое находится на следующем шаге чтения. Для его получения необходимо выполнить дополнительный вызов метода Прочитать().

Рассмотрим правильный алгоритм потокового считывания кода номенклатуры и ссылки на изображение:


ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);

НоменКод = "";
КартинкаСсылка = "";

Пока ЧтениеXML.Прочитать() Цикл
    
    Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
        
        ИмяЭлемента = ЧтениеXML.Имя;
        
        Если ИмяЭлемента = "vendorCode" Тогда
            // Переходим к следующему узлу, который содержит текст
            Если ЧтениеXML.Прочитать() И ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
                НоменКод = ЧтениеXML.Значение;
            КонецЕсли;
        ЭлЕсли ИмяЭлемента = "picture" Тогда
            // Переходим к следующему узлу для получения ссылки
            Если ЧтениеXML.Прочитать() И ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
                КартинкаСсылка = ЧтениеXML.Значение;
            КонецЕсли;
        КонецЕсли;
        
    ЭлЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
        
        Если ЧтениеXML.Имя = "offer" Тогда
            // Завершили чтение элемента товара, выполняем поиск в базе
            Если ЗначениеЗаполнено(НоменКод) Тогда
                НоменВБазе = Справочники.Номенклатура.НайтиПоКоду(НоменКод);
                // Обработка найденного объекта и сохранения картинки
            КонецЕсли;
            
            // Сбрасываем переменные для следующего товара
            НоменКод = "";
            КартинкаСсылка = "";
        КонецЕсли;
        
    КонецЕсли;
    
КонецЦикла;

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

Преимущество метода: минимальное потребление оперативной памяти. Этот подход идеально подходит для парсинга каталогов большого объема (сотни мегабайт).

Способ 2. Использование объектной модели DOM

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

Проанализируем пример чтения с помощью DOM:


ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);

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

СписокОфферов = ДокументDOM.ПолучитьЭлементыПоТегу("offer");

Для Каждого ЭлементOffer Из СписокОфферов Цикл
    
    // Получение атрибутов тега offer
    Идентификатор = ЭлементOffer.ПолучитьАтрибут("id");
    
    // Получение значения дочернего тега vendorCode
    СписокКодов = ЭлементOffer.ПолучитьЭлементыПоТегу("vendorCode");
    НоменКод = "";
    Если СписокКодов.Количество() > 0 Тогда
        НоменКод = СписокКодов[0].ТекстовоеСодержимое;
    КонецЕсли;
    
    // Получение значения дочернего тега picture
    СписокКартинок = ЭлементOffer.ПолучитьЭлементыПоТегу("picture");
    КартинкаСсылка = "";
    Если СписокКартинок.Количество() > 0 Тогда
        КартинкаСсылка = СписокКартинок[0].ТекстовоеСодержимое;
    КонецЕсли;
    
    // Поиск номенклатуры по коду
    Если ЗначениеЗаполнено(НоменКод) Тогда
        НоменВБазе = Справочники.Номенклатура.НайтиПоКоду(НоменКод);
    КонецЕсли;
    
КонецЦикла;

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

Способ 3. Десериализация с помощью Фабрики XDTO

Еще один универсальный способ обработки XML в 1С — вызов метода ФабрикаXDTO.ПрочитатьXML(). При чтении документа без явного указания схемы XDTO создает динамический объект данных, в котором теги и атрибуты преобразуются в свойства объекта 1С.


ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);

// Считываем весь XML в объект XDTO
ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);

// Обращаемся к свойствам структуры XDTO
Для Каждого ЭлементOffer Из ОбъектXDTO.shop.offers.offer Цикл
    НоменКод = ЭлементOffer.vendorCode;
    КартинкаСсылка = ЭлементOffer.picture;
    
    // Получение атрибута
    Идентификатор = ЭлементOffer.id;
КонецЦикла;

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

Резюме и рекомендации

Выяснив различие между узлами и атрибутами XML, выбирайте подходящий инструмент под конкретную задачу:

  1. Для больших прайс-листов и каталогов используйте ЧтениеXML с последовательным переходом на ТипУзлаXML.Текст.
  2. Для небольших файлов конфигураций и настроек используйте ПостроительDOM и свойство ТекстовоеСодержимое.
  3. Для сложных документов с известной структурой применяйте ФабрикуXDTO.
← На главную