Почему при чтении XML через ПостроительDOM в 1С пропадают точки в числах и как это исправить?

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

При обмене данными через формат XML программисты 1С часто сталкиваются с неожиданным поведением парсеров. Одна из самых коварных ошибок — искажение числовых значений, когда, например, число 20.0 при загрузке превращается в 200. На первый взгляд код кажется верным, файл в текстовом редакторе выглядит корректно, но объектная модель документа (DOM) выдает неверный результат. Проанализируем эту ситуацию, выясним причины такого поведения и рассмотрим надежные способы решения проблемы.

Разберем типичную ошибку в программном коде

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


// Ошибка в названии переменной и подходе
ЗаписьXML = Новый ЧтениеXML; // Используется объект чтения, но назван как запись
ЗаписьXML.ОткрытьФайл(Объект.ИмяКаталога,,,"UTF-8");
Построитель = Новый ПостроительDOM;
Документ = Построитель.Прочитать(ЗаписьXML);

Первое, на что стоит обратить внимание: объект ПостроительDOM строит дерево объектов в оперативной памяти. Если во входном потоке ЧтениеXML встречаются символы, которые парсер не может однозначно интерпретировать как часть текстового узла, или если разделитель представлен в виде специальной сущности, результат может быть непредсказуемым. Выясним, почему точка может «исчезнуть».

Причина №1: Использование числовых сущностей (HTML Entities)

Одной из наиболее вероятных причин является то, что точка в исходном XML-файле записана не как обычный символ ASCII (код 46), а как HTML-сущность, например, .. Рассмотрим подробнее: при визуальном просмотре в браузере или продвинутом текстовом редакторе такая запись автоматически отображается как точка. Однако ПостроительDOM при определенных настройках может проигнорировать неизвестную или некорректно экранированную сущность, просто «склеив» стоящие рядом цифры.

Если система, выгрузившая файл, произвела двойное кодирование спецсимволов, парсер 1С воспримет 20.0 как текстовый узел 20 и еще один узел, который может быть отброшен, если он не соответствует стандартам XML в текущем контексте. В итоге мы получаем значение 200.

Причина №2: Отсутствие типизации и использование AnyType

Объект ПостроительDOM по своей сути работает со строками. Для него значение между тегами <Quantity> — это просто набор символов. Если мы хотим, чтобы 1С понимала, что перед нами число, и правильно обрабатывала разделители, необходимо использовать типизацию. Без четко заданной схемы (XSD) система не знает, является ли точка десятичным разделителем или разделителем групп разрядов (как это бывает в некоторых региональных стандартах).

Решение через использование Фабрики XDTO и XSD-схемы

Проанализируем наиболее профессиональный и надежный способ загрузки XML-данных. Вместо простого перебора узлов DOM-дерева, воспользуемся механизмом XDTO. Этот метод позволяет автоматически преобразовывать строковые значения из XML в соответствующие типы данных 1С (Число, Дата, Булево).

Выполним следующие шаги для настройки загрузки:

  1. Создание схемы XSD: Попросим поставщика данных предоставить схему или создадим её самостоятельно, указав для поля Quantity тип xs:decimal.
  2. Загрузка схемы в конфигурацию: Импортируем XSD в пакеты XDTO.
  3. Использование Фабрики XDTO для чтения:

Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ПутьКФайлу);

// Используем типизированное чтение через фабрику
Попытка
    Данные = ФабрикаXDTO.ПрочитатьXML(Чтение);
    Количество = Данные.Quantity; // Здесь уже будет тип Число
Исключение
    Сообщить("Ошибка разбора XML: " + ОписаниеОшибки());
КонецПопытки;

Важный момент: Если использовать ФабрикаXDTO.ПрочитатьXML() без заранее определенной схемы, система все равно будет считывать данные как тип AnyType (строки), и проблема с точкой может сохраниться. Поэтому наличие схемы критически важно для корректного преобразования типов.

Решение через прямое использование ЧтениеXML

Если построение DOM-дерева не является обязательным требованием, рассмотрим альтернативный подход — последовательное чтение файла с помощью объекта ЧтениеXML. Этот метод потребляет меньше памяти и позволяет более гибко контролировать процесс обработки каждого узла. Проанализируем пример обхода:


ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ИмяФайла);

Пока ЧтениеXML.Прочитать() Цикл
    Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "Quantity" Тогда
        ЧтениеXML.Прочитать(); // Переходим к текстовому содержимому
        ЗначениеСтрокой = ЧтениеXML.Значение;
        
        // Принудительно заменяем возможные проблемы и преобразуем в число
        // Учитываем, что в XML разделитель всегда точка
        ЧисловоеЗначение = Число(СтрЗаменить(ЗначениеСтрокой, " ", ""));
        // Дальнейшая логика
    КонецЕсли;
КонецЦикла;

В данном случае мы работаем с «сырым» строковым значением. Если проблема была в специфических невидимых символах или некорректных сущностях, метод ЧтениеXML.Значение часто возвращает более предсказуемый результат, чем нормализованный узел ПостроителяDOM.

Проверка настроек выгрузки на стороне отправителя

Как показывает практика, часто проблема решается не на стороне 1С, а на стороне системы-источника. Выясним причины формирования «плохого» XML. Если отправитель использует специфические библиотеки для формирования файлов (например, старые версии PHP или самописные скрипты на Python), они могут принудительно экранировать точку.

Нужно убедиться, что:

Резюме: Если вы столкнулись с превращением 20.0 в 200, в первую очередь проверьте файл в HEX-редакторе на наличие скрытых символов. Затем попробуйте сменить ПостроительDOM на ЧтениеXML или применить ФабрикуXDTO с жестко заданной XSD-схемой. Это обеспечит корректную интерпретацию типов данных и стабильную работу вашей интеграции.

← На главную