Почему ФабрикаXDTO заменяет дефисы на подчеркивания при чтении XML и как это исправить?

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

При работе с внешними системами разработчики 1С часто сталкиваются с ситуацией, когда входящий XML-файл содержит узлы или атрибуты с дефисами в названиях (например, <new-doc>). При попытке прочитать такой файл методом ФабрикаXDTO.ПрочитатьXML(ЧтениеXML) глобальная фабрика автоматически меняет все дефисы на знаки нижнего подчеркивания (new_doc).

В этой статье мы разберем причину такого поведения платформы 1С:Предприятие и рассмотрим эффективные способы сохранения исходных имен элементов при разборе XML.

Выясним причину поведения платформы

Проанализируем механику работы ФабрикаXDTO. Когда мы вызываем метод ПрочитатьXML без предварительно загруженной XSD-схемы, платформа выполняет так называемое бессхемное чтение XML. Для того чтобы разработчик мог обращаться к свойствам прочитанного объекта через точку (например, ОбъектXDTO.new_doc), платформа принудительно приводит имена тегов к синтаксическим правилам идентификаторов языка 1С.

Так как дефис - в языке 1С является оператором вычитания, он не может присутствовать в именах переменных и свойств. По этой причине глобальная фабрика XDTO автоматически заменяет недопустимые символы на нижнее подчеркивание _.

Однако существуют проверенные решения, позволяющие обойти это ограничение или правильно связать имена тегов.

Решение 1. Использование пакетов XDTO и XSD-схем

Наиболее корректный подход при работе с XDTO — применение XSD-схемы, описывающей структуру XML-документа. Если файл загружается с использованием схемы, платформа точно знает соответствие между именем XML-тега (содержащим дефис) и именем свойства XDTO-объекта.

Рассмотрим пошагово, как реализовать этот вариант:

  1. Создадим или получим от разработчиков сторонней системы XSD-схему входящего документа.
  2. Добавим XSD-схему в ветку Пакеты XDTO в конфигураторе 1С или загрузим её динамически в коде.
  3. При создании фабрики на основе XSD-схемы вызовем метод СоздатьФабрику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.

Решение 2. Потоковое чтение через объект ЧтениеXML

Если входящий 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.Закрыть();

Решение 3. Использование документа DOM

Если файл не превышает нескольких десятков мегабайт и умещается в оперативной памяти, можно вычитать его в объектную модель 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С для бессхемного чтения. Если вам необходимо сохранить структуру данных и обработать теги с дефисами, выбирайте подходящий вариант:

  1. Пакеты XDTO (XSD-схемы) — если требуется строгая валидация и дальнейшая обратная выгрузка в XML.
  2. Объект ЧтениеXML — если обрабатываются файлы большого объема.
  3. ДокументDOM — если файл небольшого размера и требуется удобный доступ к узлам по их оригинальным именам.
← На главную