Как получить текстовое значение элемента XML из объекта XDTO при наличии атрибутов

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

При интеграции систем через XML часто возникает ситуация, когда элемент содержит не только вложенные теги, но и собственные атрибуты вместе с текстовым значением. В терминах XSD это называется Mixed Content (смешанное содержимое). Типичный пример такой структуры выглядит следующим образом: <Подразделение Код="1111"> Подразделение Самара </Подразделение>.

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

Анализ неэффективного решения

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


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

Почему так делать не стоит? Проанализируем ситуацию: платформа 1С уже один раз распарсила XML, создала дерево объектов в памяти и типизировала данные. Предложенный код заставляет систему выполнять двойную работу: сериализовать объект в строку и заново парсить его. Это ведет к избыточному потреблению памяти и процессорного времени, особенно на больших объемах данных. Кроме того, этот метод легко ломается, если атрибутов несколько или структура чуть сложнее базовой.

Решение №1: Использование механизма Последовательность()

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

Разберем по шагам, как это работает:

  1. Проверяем, есть ли у объекта последовательность.
  2. Если она есть, извлекаем из нее текстовое содержимое.
  3. Если последовательности нет, значит объект не является смешанным, и значение нужно искать в свойствах.

// Пример извлечения текста из тега <Подразделение Код="1111">Текст</Подразделение>
Если ОбъектXDTO.Последовательность() <> Неопределено Тогда
    Для Инд = 0 По ОбъектXDTO.Последовательность().Количество() - 1 Цикл
        Текст = ОбъектXDTO.Последовательность().ПолучитьТекст(Инд);
        Если ЗначениеЗаполнено(Текст) Тогда
            // Мы нашли наше текстовое значение
            ЗначениеЭлемента = СокрЛП(Текст);
            Прервать;
        КонецЕсли;
    КонецЦикла;
КонецЕсли;

Этот метод работает напрямую с данными в оперативной памяти и является максимально быстрым.

Решение №2: Работа со свойствами в anyType

Если ваш XML читается без предварительно загруженной схемы XSD (используется тип anyType), 1С может не создавать явную последовательность. В этом случае текстовое содержимое элемента часто помещается в свойство с пустым именем или специальное системное свойство.

Проанализируем ситуацию динамического перебора свойств:


Для Каждого Свойство Из ОбъектXDTO.Свойства() Цикл
    // Атрибуты и вложенные элементы будут иметь имена
    // Текстовое содержимое в anyType может отображаться как свойство без имени
    Попытка
        Значение = ОбъектXDTO.Получить(Свойство);
        ИмяСвойства = Свойство.Имя;
        
        Если ПустаяСтрока(ИмяСвойства) Тогда
            // Это и есть текстовое содержимое элемента
            Результат = Значение;
        КонецЕсли;
    Исключение
        // Обработка возможных ошибок доступа
    КонецПопытки;
КонецЦикла;

Решение №3: СериализаторXDTO

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


// Предположим, ОбъектXDTO содержит данные, понятные платформе
Попытка
    Данные1С = СериализаторXDTO.ПрочитатьXDTO(ОбъектXDTO);
    // Теперь Данные1С могут быть Структурой или Ссылкой
    // Значение будет доступно напрямую: Данные1С.Наименование
Исключение
    // Если объект не соответствует ни одному типу конфигурации
КонецПопытки;

Важные нюансы и рекомендации

Пространства имен (Namespaces): Часто значение не удается получить просто по имени ОбъектXDTO.Имя, если элемент находится в специфическом пространстве имен. Всегда проверяйте URI пространства имен вашего типа. Для надежности используйте метод ОбъектXDTO.Получить(ОбъектXDTO.Тип().Свойства.Получить("Имя")).

Проверка на установленность: Перед чтением значения полезно вызвать метод ОбъектXDTO.Установлено("ИмяСвойства"). Это критически важно для понимания разницы между «пустым значением» и «отсутствием тега в XML вовсе».

Производительность: Выясним причину замедления работы при больших объемах данных. Если вы используете метод из Сообщения 0 (через ЗаписьXML), то при обработке файла в 100 Мб вы создадите временную строку такого же размера, что может привести к Out of Memory. Всегда отдавайте предпочтение методам Последовательность() или прямой типизации через ФабрикуXDTO.

Резюме: Для извлечения текста из тегов с атрибутами всегда в первую очередь проверяйте ОбъектXDTO.Последовательность(). Это штатный, быстрый и надежный механизм платформы 1С для работы со сложными XML-структурами.

← На главную