Как исправить ошибку десериализации объекта при обмене данными через XDTO, XML и XSL

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

При организации обмена данными между различными конфигурациями 1С (например, между самописной системой и «1С:Бухгалтерией») программисты часто сталкиваются с ошибкой: «Не удалось десериализовать объект... возможно поменялась структура конфигурации: Ошибка при вызове метода контекста (ПрочитатьXML)». Эта проблема возникает в момент, когда принимающая база пытается преобразовать входящий XML-поток в объект XDTO, но структура этого потока не соответствует ожиданиям схемы XDTO-пакета.

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

Анализируем причину возникновения ошибки

Проанализируем ситуацию: метод ПрочитатьXML в контексте работы с XDTO крайне чувствителен к любым отклонениям от схемы. Основными причинами сбоя обычно являются:

  1. Несовпадение состава полей: В базе-источнике в XDTO-пакет добавлены новые реквизиты, которых еще нет в базе-приемнике.
  2. Нарушение порядка следования элементов: В XML-схемах (XSD) элементы часто описываются внутри тега xs:sequence. Это означает, что 1С ожидает увидеть поля в XML-файле строго в том порядке, в котором они описаны в пакете. Если поле IsFolder идет первым в одной базе и вторым в другой — десериализация упадет.
  3. Различия в типах данных: Например, в одной базе реквизит имеет тип string, а в другой — ссылку на перечисление.
  4. Лишние данные после трансформации: Если используется XSLT-преобразование, оно может некорректно формировать итоговый пакет, оставляя «мусорные» теги, которые не описаны в целевом XDTO-пакете.

Посмотрим на пример кода, который обычно используется для отправки пакета через Web-сервис:


Функция ОтправитьПакетДанныхВСмежнуюБазу(СтруктураОтправкиПакета)
    СтруктураОтправкиПакета.НомерПакета = СтруктураОтправкиПакета.НомерПакета + 1;
    XML_Message = ПолучитьТекстСообщенияПакетаДанных(СтруктураОтправкиПакета.Пакет);
    
    // Преобразование XML с помощью XSLT для приведения к структуре приемника
    XML_Message_Recipient_Struckure = ПреобразоватьТекстВСтруктуруПриемника(XML_Message, СтруктураОтправкиПакета);
    
    Если XML_Message_Recipient_Struckure = Неопределено Тогда
        Возврат Ложь;
    КонецЕсли; 

    Попытка
        // Вызов метода Web-сервиса в приемнике
        РезультатЗагрузки = СтруктураОтправкиПакета.ПроксиWSСсылкиОбменаСоСмежнойБазой.uploadDataPackage(
            XML_Message_Recipient_Struckure, 
            СтруктураОтправкиПакета.НомерПакета, 
            СтруктураОтправкиПакета.Приоритет, 
            СтруктураОтправкиПакета.СразуСтавитьВОчередь, 
            СтруктураОтправкиПакета.СтруктураИдентификацииСообщения.Ид);
    Исключение
        // Обработка ошибки соединения
        Возврат Ложь;
    КонецПопытки;
    
    Возврат Истина;
КонецФункции

Сравнение XDTO-пакетов через экспорт схем

Выясним причину расхождения, выгрузив схемы XSD из обеих конфигураций. Для этого в дереве метаданных нужно найти используемый XDTO-пакет, нажать на него правой кнопкой мыши и выбрать «Экспорт XML-схемы».

Рассмотрим пример реального расхождения для справочника ОбщероссийскийКлассификаторОсновныхФондов. В самописной базе схема выглядит так:


<xs:complexType name="CatalogObject.ОбщероссийскийКлассификаторОсновныхФондов">
    <xs:sequence>
        <xs:element name="IsFolder" type="xs:boolean"/>
        <xs:element name="Ref" type="tns:CatalogRef.ОбщероссийскийКлассификаторОсновныхФондов"/>
        <xs:element name="DeletionMark" type="xs:boolean"/>
        <xs:element name="Parent" type="tns:CatalogRef.ОбщероссийскийКлассификаторОсновныхФондов"/>
        <xs:element name="Code" type="xs:string"/>
        <xs:element name="Description" type="xs:string"/>
        <xs:element name="КонтрольноеЧисло" type="xs:string"/>
        <xs:element name="НаименованиеГруппировки" type="xs:string"/>
        <xs:element name="АмортизационнаяГруппа" type="tns:EnumRef.АмортизационныеГруппы"/>
        <xs:element name="хлпКоэффициентУскорения" type="xs:decimal"/>
    </xs:sequence>
</xs:complexType>

А в базе «1С:Бухгалтерия» порядок и состав элементов другие:


<xs:complexType name="CatalogObject.ОбщероссийскийКлассификаторОсновныхФондов">
    <xs:sequence>
        <xs:element name="Ref" type="tns:CatalogRef.ОбщероссийскийКлассификаторОсновныхФондов"/>
        <xs:element name="DeletionMark" type="xs:boolean"/>
        <xs:element name="Parent" type="tns:CatalogRef.ОбщероссийскийКлассификаторОсновныхФондов"/>
        <xs:element name="Code" type="xs:string"/>
        <xs:element name="Description" type="xs:string"/>
        <xs:element name="PredefinedDataName" type="xs:string" minOccurs="0"/>
        <xs:element name="КонтрольноеЧисло" type="xs:string"/>
        <xs:element name="НаименованиеГруппировки" type="xs:string"/>
    </xs:sequence>
</xs:complexType>

Важное наблюдение: В приемнике отсутствует поле хлпКоэффициентУскорения, а поле IsFolder вообще не предусмотрено в начале последовательности. Это гарантированно приведет к ошибке ПрочитатьXML, так как механизм XDTO в 1С ожидает элементы строго по списку.

Способы решения проблемы

Разберем по шагам, как можно исправить данную ситуацию. У нас есть два основных пути.

Вариант 1: Синхронизация XDTO-пакетов

Это самый правильный метод. Нам необходимо привести структуру пакета в базе-приемнике к виду базы-источника (или наоборот).

  1. В конфигураторе базы-приемника откройте нужный XDTO-пакет.
  2. Вручную добавьте недостающие свойства (например, хлпКоэффициентУскорения) с соответствующими типами.
  3. Важно: Проверьте порядок свойств. Переместите их с помощью стрелок «Вверх»/«Вниз» так, чтобы они располагались идентично базе-источнику.
  4. Если база-приемник опубликована на веб-сервере, после обновления конфигурации обязательно перезапустите веб-сервер (например, командой iisreset для IIS), так как описания пакетов кэшируются.

Вариант 2: Использование XSL-преобразования для очистки данных

Если вы не хотите менять структуру конфигурации «1С:Бухгалтерия», вы можете подправить XSLT-шаблон, который используется в функции ПреобразоватьТекстВСтруктуруПриемника. Настройте шаблон так, чтобы он:

Как отладить принимающую сторону

Чтобы точно понять, на каком поле спотыкается система, необходимо запустить отладку на стороне Web-сервиса базы-приемника. Рассмотрим, как это сделать:

  1. Убедитесь, что сервер 1С в базе-приемнике запущен с ключом -debug.
  2. В конфигураторе приемника перейдите в меню Отладка — Подключение — Автоматическое подключение и установите флажок «Web-сервисы».
  3. Установите точку останова в модуле вашего Web-сервиса (метод uploadDataPackage).
  4. В момент вызова обмена из источника, выполнение остановится в приемнике. Вы сможете по шагам пройти выполнение функции ПрочитатьXML и увидеть, какой именно элемент вызывает ошибку.

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

← На главную