При организации обмена между мобильной платформой и центральной базой 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]
// Чтение данных и фиксация изменений...
КонецФункции
Сбой происходит на строке вызова метода НачатьЧтение() или непосредственно при инициализации чтения. Выясним основные причины такого поведения.
Если в процессе вызова метода прокси происходят сетевые сбои, таймауты или ошибки авторизации на веб-сервере (IIS / Apache), веб-сервер возвращает стандартную HTML-страницу с текстом ошибки (например, код 401, 403, 500 или 503). Попадая в строковую переменную, такой текст не может быть разобран парсером XML и выдает ошибку с первой строки и первого символа [1,1].
Для обнаружения проблемы выполним протоколирование входящих данных перед их разбором:
Если НЕ ЗначениеЗаполнено(СообщениеОбмена) Тогда
ЗаписьЖурналаРегистрации("Обмен.Ошибка", УровеньЖурналаРегистрации.Ошибка, , , "Получено пустое тело сообщения");
ВызватьИсключение("Тело сообщения обмена пустое.");
КонецЕсли;
Тип ХранилищеЗначения использует внутренний бинарный формат сериализации платформы 1С. При несовпадении версий платформы мобильного клиента и сервера 1С внутренний формат упакованных данных может быть прочитан некорректно, из-за чего вызов ДанныеМобильногоПриложения.Получить() возвращает Неопределено или пустую строку.
Способ решения: замена ХранилищеЗначения на стандартный тип XDTO xs:base64Binary (в коде 1С соответствует типу ДвоичныеДанные) или xs:string.
xs:base64Binary.Метод ЧтениеXML.УстановитьСтроку() ожидает чистый текст без служебных непечатаемых символов. Если строка содержит метку BOM (Символ(65279)), парсер не может корректно распознать открывающий тег XML.
Разберем два варианта устранения проблемы с BOM:
Если СтрНачинаетсяС(СообщениеОбмена, Символ(65279)) Тогда
СообщениеОбмена = Сред(СообщениеОбмена, 2);
КонецЕсли;
ЧтениеXML.УстановитьСтроку(СообщениеОбмена);
ОткрытьФайл() автоматически определяет кодировку и корректно отсекает BOM.
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xml");
СообщениеОбмена.Записать(ИмяВременногоФайла); // Если СообщениеОбмена имеет тип ДвоичныеДанные
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ИмяВременногоФайла);
ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
ЧтениеСообщения.НачатьЧтение(ЧтениеXML);
// Выполнение обработки сообщения
ЧтениеСообщения.ЗакончитьЧтение();
ЧтениеXML.Закрыть();
УдалитьФайлы(ИмяВременногоФайла);
В отличие от запроса метаданных WSDL, реальный обмен передает объемные пакеты данных. При нестабильном мобильном интернете или превышении лимитов веб-сервер прерывает входящий запрос.
Проверим настройки публикации:
maxAllowedContentLength в файле конфигурации web.config, а также увеличить uploadReadAheadSize в конфигурации сервера.LimitRequestBody, Timeout и KeepAliveTimeout.В некоторых версиях платформы 1С:Предприятие 8.3 (в частности, в ветке 8.3.7 при работе в клиент-серверном варианте под управлением СУБД) наблюдались ошибки десериализации SOAP-пакетов определенного размера (от 100 до 200 Кб). Для устранения системных сбоев рекомендуется обновить серверную платформу до стабильных актуальных релизов.
Для надежного обмена между мобильными устройствами и сервером 1С рекомендуется отказаться от SOAP-веб-сервисов в пользу HTTP-сервисов. Это обеспечивает:
HTTPСервисЗапрос.ПолучитьТелоКакДвоичныеДанные() или ПолучитьТелоКакСтроку() без накладных расходов на SOAP-конвертацию.