При интеграции систем через 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, создала дерево объектов в памяти и типизировала данные. Предложенный код заставляет систему выполнять двойную работу: сериализовать объект в строку и заново парсить его. Это ведет к избыточному потреблению памяти и процессорного времени, особенно на больших объемах данных. Кроме того, этот метод легко ломается, если атрибутов несколько или структура чуть сложнее базовой.
Самый правильный и эффективный способ получить текст из элемента со смешанным содержимым — это использование метода Последовательность(). Если тип объекта XDTO определен как mixed (смешанный), у него появляется специальная коллекция, хранящая данные в порядке их появления в XML.
Разберем по шагам, как это работает:
// Пример извлечения текста из тега <Подразделение Код="1111">Текст</Подразделение>
Если ОбъектXDTO.Последовательность() <> Неопределено Тогда
Для Инд = 0 По ОбъектXDTO.Последовательность().Количество() - 1 Цикл
Текст = ОбъектXDTO.Последовательность().ПолучитьТекст(Инд);
Если ЗначениеЗаполнено(Текст) Тогда
// Мы нашли наше текстовое значение
ЗначениеЭлемента = СокрЛП(Текст);
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Этот метод работает напрямую с данными в оперативной памяти и является максимально быстрым.
Если ваш XML читается без предварительно загруженной схемы XSD (используется тип anyType), 1С может не создавать явную последовательность. В этом случае текстовое содержимое элемента часто помещается в свойство с пустым именем или специальное системное свойство.
Проанализируем ситуацию динамического перебора свойств:
Для Каждого Свойство Из ОбъектXDTO.Свойства() Цикл
// Атрибуты и вложенные элементы будут иметь имена
// Текстовое содержимое в anyType может отображаться как свойство без имени
Попытка
Значение = Объект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-структурами.