При работе с внешними системами разработчики 1С часто сталкиваются с ситуацией, когда входящий XML-файл содержит узлы или атрибуты с дефисами в названиях (например, <new-doc>). При попытке прочитать такой файл методом ФабрикаXDTO.ПрочитатьXML(ЧтениеXML) глобальная фабрика автоматически меняет все дефисы на знаки нижнего подчеркивания (new_doc).
В этой статье мы разберем причину такого поведения платформы 1С:Предприятие и рассмотрим эффективные способы сохранения исходных имен элементов при разборе XML.
Проанализируем механику работы ФабрикаXDTO. Когда мы вызываем метод ПрочитатьXML без предварительно загруженной XSD-схемы, платформа выполняет так называемое бессхемное чтение XML. Для того чтобы разработчик мог обращаться к свойствам прочитанного объекта через точку (например, ОбъектXDTO.new_doc), платформа принудительно приводит имена тегов к синтаксическим правилам идентификаторов языка 1С.
Так как дефис - в языке 1С является оператором вычитания, он не может присутствовать в именах переменных и свойств. По этой причине глобальная фабрика XDTO автоматически заменяет недопустимые символы на нижнее подчеркивание _.
Однако существуют проверенные решения, позволяющие обойти это ограничение или правильно связать имена тегов.
Наиболее корректный подход при работе с XDTO — применение XSD-схемы, описывающей структуру XML-документа. Если файл загружается с использованием схемы, платформа точно знает соответствие между именем XML-тега (содержащим дефис) и именем свойства XDTO-объекта.
Рассмотрим пошагово, как реализовать этот вариант:
СоздатьФабрикуXDTO.Посмотрим на пример кода для динамической загрузки схемы и чтения XML:
// Создаем чтение для файла XSD-схемы
ЧтениеСхемы = Новый ЧтениеXML;
ЧтениеСхемы.ОткрытьФайл("C:\schemas\document.xsd");
// Загружаем схему и создаем фабрику XDTO
ВозможнаяСхема = ФабрикаXDTO.ПрочитатьXML(ЧтениеСхемы);
СхемаXML = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("http://www.w3.org/2001/XMLSchema", "schema"));
ФабрикаСхемы = СоздатьФабрикуXDTO(ЧтениеСхемы);
// Читаем сам XML-файл с помощью созданной фабрики
ЧтениеФайла = Новый ЧтениеXML;
ЧтениеФайла.ОткрытьФайл("C:\data\input.xml");
ОбъектXDTO = ФабрикаСхемы.ПрочитатьXML(ЧтениеФайла);
ЧтениеФайла.Закрыть();
В этом случае при сериализации и обратно при обратной выгрузке через ЗаписатьXML дефисы будут корректно сохраняться согласно правилам, заданным в XSD.
Если входящий XML имеет огромный размер или создание XSD-схемы нецелесообразно, лучше отказаться от ФабрикаXDTO в пользу последовательного чтения через ЧтениеXML. На уровне низкоуровневого чтения платформа не пытается приводить имена тегов к переменным 1С и возвращает их в виде обычных строк без искажений.
Разберем пример обхода узлов с сохранением оригинальных имен:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл("C:\data\input.xml");
Пока ЧтениеXML.Прочитать() Цикл
Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
// Считываем оригинальное имя тега с дефисами
ИмяТега = ЧтениеXML.ЛокальноеИмя;
Если ИмяТега = "new-doc_op" Тогда
// Обрабатываем нужный элемент
Пока ЧтениеXML.Прочитать() Цикл
Если ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
ЗначениеЭлемента = ЧтениеXML.Значение;
ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЦикла;
ЧтениеXML.Закрыть();
Если файл не превышает нескольких десятков мегабайт и умещается в оперативной памяти, можно вычитать его в объектную модель DOM с помощью объекта ДокументDOM. Объектная модель DOM полностью сохраняет исходную структуру файла, включая спецсимволы и дефисы.
Рассмотрим, как прочитать XML через DOM:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл("C:\data\input.xml");
СтроительDOM = Новый СтроительДокументаDOM;
ДокументDOM = СтроительDOM.Прочитать(ЧтениеXML);
// Получаем список узлов по оригинальному имени тега с дефисом
Элементы = ДокументDOM.ПолучитьЭлементыПоИмениТэга("new-doc_op");
Для Каждого ЭлементИзСписка Из Элементы Цикл
ТекстовоеСодержимое = ЭлементИзСписка.ТекстовоеСодержимое;
КонецЦикла;
ЧтениеXML.Закрыть();
Замена дефисов на нижние подчеркивания при использовании ФабрикаXDTO.ПрочитатьXML — это стандартное поведение платформы 1С для бессхемного чтения. Если вам необходимо сохранить структуру данных и обработать теги с дефисами, выбирайте подходящий вариант: