Как исправить ошибку разбора XML [1,1] при обмене данными между мобильным приложением и сервером 1С?

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

При организации обмена между мобильной платформой и центральной базой 1С разработчики нередко сталкиваются с исключением вида "Ошибка разбора XML [1,1] - Extra content at the end of the document" или аналогичными сбоями разбора на начальной позиции документа. Данная ошибка свидетельствует о том, что парсер ЧтениеXML получил пустую строку, некорректно сформированный текст или HTML-ответ вместо ожидаемого тела пакета XML.

Разберем типичный сценарий возникновения сбоя, проанализируем фрагменты кода и рассмотрим надежные способы решения проблемы.

Анализ механизма возникновения ошибки

Посмотрим на пример отправки данных из мобильного приложения на сервер 1С через SOAP веб-сервис:


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

На стороне сервера веб-сервис принимает параметр, распаковывает переданное значение и начинает чтение сообщения обмена:


Функция ЗаписатьДанные(ИмяУстройства, ДанныеМобильногоПриложения)
    
    УзелОбмена = ПланыОбмена.МобильноеПриложениеКонтрольКультур.НайтиПоКоду(ИмяУстройства); 
    Если УзелОбмена.Пустая() Тогда
        ВызватьИсключение("Неизвестное устройство: " + ИмяУстройства);
    КонецЕсли;
    
    СообщениеОбмена = ДанныеМобильногоПриложения.Получить();
    
    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.УстановитьСтроку(СообщениеОбмена);
    
    ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
    ЧтениеСообщения.НачатьЧтение(ЧтениеXML); // Ошибка разбора XML [1,1]
    
    // Чтение данных и фиксация изменений...
    
КонецФункции

Сбой происходит на строке вызова метода НачатьЧтение() или непосредственно при инициализации чтения. Выясним основные причины такого поведения.

Причина 1: Возврат HTML-страницы с ошибкой веб-сервера вместо XML

Если в процессе вызова метода прокси происходят сетевые сбои, таймауты или ошибки авторизации на веб-сервере (IIS / Apache), веб-сервер возвращает стандартную HTML-страницу с текстом ошибки (например, код 401, 403, 500 или 503). Попадая в строковую переменную, такой текст не может быть разобран парсером XML и выдает ошибку с первой строки и первого символа [1,1].

Для обнаружения проблемы выполним протоколирование входящих данных перед их разбором:


Если НЕ ЗначениеЗаполнено(СообщениеОбмена) Тогда
    ЗаписьЖурналаРегистрации("Обмен.Ошибка", УровеньЖурналаРегистрации.Ошибка, , , "Получено пустое тело сообщения");
    ВызватьИсключение("Тело сообщения обмена пустое.");
КонецЕсли;

Причина 2: Использование типа «ХранилищеЗначения» в параметрах веб-сервиса

Тип ХранилищеЗначения использует внутренний бинарный формат сериализации платформы 1С. При несовпадении версий платформы мобильного клиента и сервера 1С внутренний формат упакованных данных может быть прочитан некорректно, из-за чего вызов ДанныеМобильногоПриложения.Получить() возвращает Неопределено или пустую строку.

Способ решения: замена ХранилищеЗначения на стандартный тип XDTO xs:base64Binary (в коде 1С соответствует типу ДвоичныеДанные) или xs:string.

  1. В операции веб-сервиса изменим тип входного параметра на xs:base64Binary.
  2. На мобильном клиенте перед отправкой упакуем XML-сообщение в двоичные данные или zip-архив.
  3. На сервере получим двоичные данные и распакуем их обратно в строку или сохраним во временный файл.

Причина 3: Наличие метки порядка байтов (BOM) при использовании УстановитьСтроку

Метод ЧтениеXML.УстановитьСтроку() ожидает чистый текст без служебных непечатаемых символов. Если строка содержит метку BOM (Символ(65279)), парсер не может корректно распознать открывающий тег XML.

Разберем два варианта устранения проблемы с BOM:

  1. Программное удаление символа BOM перед установкой строки:
    
    Если СтрНачинаетсяС(СообщениеОбмена, Символ(65279)) Тогда
        СообщениеОбмена = Сред(СообщениеОбмена, 2);
    КонецЕсли;
    ЧтениеXML.УстановитьСтроку(СообщениеОбмена);
    
  2. Переход на потоковое чтение через временный файл: Использование метода ОткрытьФайл() автоматически определяет кодировку и корректно отсекает BOM.
    
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xml");
    СообщениеОбмена.Записать(ИмяВременногоФайла); // Если СообщениеОбмена имеет тип ДвоичныеДанные
    
    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.ОткрытьФайл(ИмяВременногоФайла);
    
    ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
    ЧтениеСообщения.НачатьЧтение(ЧтениеXML);
    
    // Выполнение обработки сообщения
    ЧтениеСообщения.ЗакончитьЧтение();
    ЧтениеXML.Закрыть();
    
    УдалитьФайлы(ИмяВременногоФайла);
    

Причина 4: Ограничения размера тела запроса и таймауты веб-сервера

В отличие от запроса метаданных WSDL, реальный обмен передает объемные пакеты данных. При нестабильном мобильном интернете или превышении лимитов веб-сервер прерывает входящий запрос.

Проверим настройки публикации:

  1. Для IIS: проверить и увеличить параметр maxAllowedContentLength в файле конфигурации web.config, а также увеличить uploadReadAheadSize в конфигурации сервера.
  2. Для Apache: проверить значения директив LimitRequestBody, Timeout и KeepAliveTimeout.

Причина 5: Платформенные ошибки релизов

В некоторых версиях платформы 1С:Предприятие 8.3 (в частности, в ветке 8.3.7 при работе в клиент-серверном варианте под управлением СУБД) наблюдались ошибки десериализации SOAP-пакетов определенного размера (от 100 до 200 Кб). Для устранения системных сбоев рекомендуется обновить серверную платформу до стабильных актуальных релизов.

Рекомендация: Переход на HTTP-сервисы

Для надежного обмена между мобильными устройствами и сервером 1С рекомендуется отказаться от SOAP-веб-сервисов в пользу HTTP-сервисов. Это обеспечивает:

  1. Прямой доступ к телу запроса через HTTPСервисЗапрос.ПолучитьТелоКакДвоичныеДанные() или ПолучитьТелоКакСтроку() без накладных расходов на SOAP-конвертацию.
  2. Простой контроль ошибок HTTP-протокола (явная передача статус-кодов 4xx и 5xx).
  3. Независимость от формата внутренней сериализации платформы.
← На главную