При работе с интеграциями и обмене данными программисты 1С часто сталкиваются с необходимостью разбора XML-файлов. Одним из самых мощных и быстрых инструментов для этого является Фабрика XDTO. Однако стандартные методы обращения к свойствам объекта XDTO могут поставить в тупик, когда структура XML-узла содержит одновременно и атрибуты, и текстовое значение. В этой статье мы подробно разберем, почему возникает такая сложность и какими способами можно извлечь заветные данные.
Рассмотрим ситуацию. У нас есть стандартный элемент XML, который содержит только значение:
<csdo:ProductId>101803492600519</csdo:ProductId>
При чтении такого элемента через ФабрикаXDTO.ПрочитатьXML(ЧтениеXML) 1С создает объект, где значение доступно напрямую. Но как только структура усложняется атрибутами, как в примере ниже, привычный подход перестает работать:
<casdo:CleanNetMassMeasure measurementUnitCode="166" measurementUnitCodeListId="2016">0.192</casdo:CleanNetMassMeasure>
В данном случае элемент CleanNetMassMeasure технически становится Complex Type с Simple Content (сложным типом с простым содержимым). Платформа 1С считывает атрибуты measurementUnitCode и measurementUnitCodeListId как свойства объекта XDTO, но само текстовое значение "0.192" оказывается скрыто внутри структуры объекта, так как оно не привязано ни к одному именованному свойству.
Самый быстрый и универсальный способ, предложенный в сообществе, — это использование метода Последовательность(). Если у объекта XDTO нет явно заданного свойства для хранения текстового значения (что часто бывает при динамическом чтении без жесткой схемы), 1С помещает этот текст в так называемую последовательность.
Разберем, как программно получить доступ к этому значению. Предположим, что СтрокаТоварыXDTO — это наш считанный объект. Для извлечения текста используем следующую конструкцию:
// Извлекаем текстовое значение из первого узла последовательности
ТекстовоеЗначение = СтрокаТоварыXDTO.Последовательность().ПолучитьТекст(0);
Важные нюансы этого метода:
ПолучитьТекст(0) обращается к самому первому текстовому блоку внутри тега. В большинстве случаев (как в примере с массой) это именно то, что нужно.В некоторых случаях, в зависимости от настроек XDTO-пакета или версии платформы, 1С может автоматически сопоставить текстовое содержимое элемента со свойством Значение (или Value в англоязычной локализации). Прежде чем использовать работу с последовательностями, рекомендуется проверить наличие этого свойства:
Если СвойствоОбъектаXDTO(ОбъектXDTO, "Значение") Тогда
НужныйТекст = ОбъектXDTO.Значение;
КонецЕсли;
Это более «чистый» способ обращения к данным, если структура XSD-схемы это подразумевает. Однако, если схема создается динамически «на лету» при чтении, этот вариант может не сработать.
Рассмотрим ошибку, упомянутую в обсуждении. Часто разработчики пытаются использовать функцию XMLЗначение для преобразования типа, передавая в нее весь объект XDTO:
// ОШИБКА: Неверный второй параметр
Результат = XMLЗначение(Тип("Число"), СтрокаТоварыXDTO.CustomsValueAmount);
Проанализируем причину сбоя. Функция XMLЗначение ожидает на вход либо простую строку, либо объект типа ЧтениеXML. Когда мы передаем в нее ОбъектXDTO, содержащий в себе еще и атрибуты, функция не понимает, какую именно часть этого сложного объекта нужно преобразовывать в число. Правильный алгоритм действий должен быть таким:
Последовательность().ПолучитьТекст(0).Если вы сами проектируете XDTO-пакет для импорта подобных файлов, вы можете избежать сложностей с последовательностями, правильно настроив структуру типа. Разберем по шагам, как это сделать:
decimal из пространства имен http://www.w3.org/2001/XMLSchema).После такой настройки при чтении XML свойство Значение появится у объекта автоматически, и оно уже будет иметь правильный тип (число, дата и т.д.), что избавит вас от необходимости ручного преобразования через XMLЗначение.
Если структура XML слишком непредсказуема или XDTO-пакет получается чрезмерно громоздким, мы можем комбинировать XDTO с классическим объектом ЧтениеXML. В момент, когда ЧтениеXML находится на нужном узле, мы можем извлечь данные следующим образом:
// Читаем атрибуты напрямую из потока
КодЕдиницы = ЧтениеXML.ПолучитьАтрибут("measurementUnitCode");
// Читаем только текстовое содержимое, пропуская вложенные элементы
ТекстовоеЗначение = ЧтениеXML.ПрочитатьСодержимое();
Этот метод полезен, когда вам нужно быстро «выхватить» значение одного конкретного поля, не описывая всю огромную структуру файла в объектах XDTO.
Резюмируем: при работе с XML через XDTO в 1С всегда помните, что любой элемент с атрибутами становится «объектом». Если вам нужно достать текст из такого объекта, вашим лучшим другом будет метод Последовательность().ПолучитьТекст(0) или правильная настройка Simple Content в схеме данных.