Работа с веб-сервисами SAP часто преподносит сюрпризы 1С-разработчикам. Одной из самых коварных проблем является ситуация, когда стандартные механизмы платформы, такие как WSПрокси и ФабрикаXDTO, отказываются принимать ответ от сервера, выдавая фатальные ошибки разбора XML. Проанализируем типичную ситуацию: вы подключаетесь к сервису, вызываете метод, но вместо ожидаемого объекта XDTO получаете сообщение «Ошибка разбора XML: Document is empty» или «Структура объекта не соответствует типу». Разберем по шагам, почему это происходит и как заставить 1С корректно прочитать данные.
Одной из главных архитектурных особенностей интеграции с SAP является передача данных в формате «Nested XML». Согласно спецификации WSDL, поле ответа может быть описано как простая строка (string), но фактически SAP передает в этой строке целый XML-документ. Чтобы этот вложенный документ не «сломал» структуру основного SOAP-пакета, сервер экранирует управляющие символы XML.
Рассмотрим ситуацию подробнее. Символ < превращается в <, а символ > в >. Когда 1С получает такой ответ через WSПрокси, она видит обычный текст. Если вы попытаетесь передать этот текст напрямую в метод ПрочитатьXML(), возникнет ошибка, так как с точки зрения парсера это не валидный XML-документ, а просто набор символов.
Решение: Нам необходимо выполнить обратное преобразование (Unescape). Проанализируем код, который поможет очистить полученную строку:
// Получаем ответ от сервиса как строку
ТекстОтвета = ОтветСервиса.ДокументВВидеСтроки;
// Заменяем экранированные последовательности на символы разметки
ТекстОтвета = СтрЗаменить(ТекстОтвета, "<", "<");
ТекстОтвета = СтрЗаменить(ТекстОтвета, ">", ">");
ТекстОтвета = СтрЗаменить(ТекстОтвета, "&", "&");
ТекстОтвета = СтрЗаменить(ТекстОтвета, """, """");
ТекстОтвета = СтрЗаменить(ТекстОтвета, "'", "'");
Только после такой замены ФабрикаXDTO сможет распознать структуру документа.
Если при вызове ЧтениеXML.УстановитьСтроку(ФайлXML) вы получаете ошибку «[1,1] Фатальная ошибка: Document is empty», хотя переменная ФайлXML явно содержит текст, проблема кроется в «мусоре» в начале строки. Проанализируем ситуацию: системы SAP при формировании ответа могут добавлять HTTP-заголовки, спецификации кодировки или BOM (Byte Order Mark).
Метод УстановитьСтроку() ожидает, что XML начнется немедленно. Если в первом байте находится невидимый символ или техническая информация SOAP-конверта, парсер выдает фатальную ошибку. Посмотрим, как очистить строку от лишних префиксов:
// Ищем начало тега XML
ПозицияНачала = Найти(ФайлXML, "<");
Если ПозицияНачала > 1 Тогда
ЧистыйXML = Сред(ФайлXML, ПозицияНачала);
ИначеЕсли ПозицияНачала = 0 Тогда
Сообщить("Строка не является XML документом!");
Возврат;
КонецЕсли;
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(ЧистыйXML);
Часто разработчики SAP меняют структуру ответа, не обновляя WSDL-описание на стороне сервиса. В этом случае WSПрокси в 1С пытается сопоставить пришедший XML со старой схемой XDTO и падает с ошибкой «Структура объекта не соответствует типу». Выясним, как обойти жесткую проверку типов.
Если автоматическое преобразование через WSПрокси не работает, нам стоит отказаться от использования типизированного ответа. Вместо того чтобы ожидать ОбъектXDTO, мы можем попробовать получить «сырые» данные. Однако в 1С при использовании WSПрокси это сделать сложно. Рассмотрим альтернативный путь — использование HTTPСоединение.
Разберем алгоритм работы через HTTPЗапрос:
HTTPОтвет и извлекаем из него Тело как строку.Сред, Найти) вырезаем нужный нам фрагмент XML из SOAP-оболочки.ФабрикаXDTO.ПрочитатьXML(), используя локальную фабрику, созданную на основе схемы (XSD).Выясним, почему ФабрикаXDTO.ПрочитатьXML(Чтение) может выдавать ошибку, даже если XML валиден. Платформа 1С должна знать, к какому пакету XDTO относится читаемый файл. Если в файле указано пространство имен (атрибут xmlns), которого нет в текущей фабрике, чтение не удастся.
Посмотрим на правильный способ вызова метода чтения, если мы используем внешнюю схему:
// Прокси.ФабрикаXDTO уже содержит все схемы из WSDL
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(ЧистыйXML);
// Определяем тип, к которому нужно привести XML
ТипОбъекта = Прокси.ФабрикаXDTO.Тип("http://sap.com/xi/your_namespace", "ИмяТипа");
// Читаем с явным указанием типа
Данные = Прокси.ФабрикаXDTO.ПрочитатьXML(Чтение, ТипОбъекта);
Для успешного решения проблем с XML-сервисами SAP рекомендуем выполнить следующие действия:
Base64. В 1С их нужно декодировать методом Base64Значение().UTF-16. При сохранении в файл и последующем чтении в 1С убедитесь, что кодировка указана явно, иначе метод ОткрытьФайл() может прочитать весь документ как одну бесконечную строку с нечитаемыми символами.WSОпределения, указывая актуальный URL или путь к файлу .wsdl.ФабрикуXDTO, запишите ее в текстовый файл через ТекстовыйДокумент. Это позволит вам увидеть реальное содержимое (включая невидимые символы) в HEX-редакторе.Резюмируя: ошибка Document is empty в 90% случаев означает, что вы пытаетесь скормить парсеру не чистый XML, а строку с техническим заголовком или экранированными символами. Очистка строки и приведение ее к стандартному виду XML-документа решают проблему в большинстве случаев.